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
21 #include "wine/port.h"
24 #define __USE_ISOC9X 1
25 #define __USE_ISOC99 1
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
38 #define finitef(x) isfinite(x)
41 /* FIXME: Does not work with -NAN and -0. */
43 #define signbit(x) ((x) < 0)
46 #define _DOMAIN 1 /* domain error in argument */
47 #define _SING 2 /* singularity */
48 #define _OVERFLOW 3 /* range overflow */
49 #define _UNDERFLOW 4 /* range underflow */
51 typedef int (CDECL
*MSVCRT_matherr_func
)(struct MSVCRT__exception
*);
52 typedef double LDOUBLE
; /* long double is just a double */
54 static MSVCRT_matherr_func MSVCRT_default_matherr_func
= NULL
;
56 static BOOL sse2_supported
;
57 static BOOL sse2_enabled
;
59 void msvcrt_init_math(void)
61 sse2_supported
= sse2_enabled
= IsProcessorFeaturePresent( PF_XMMI64_INSTRUCTIONS_AVAILABLE
);
64 /*********************************************************************
67 int CDECL
MSVCRT__matherr(struct MSVCRT__exception
*e
)
72 TRACE("(%p = {%d, \"%s\", %g, %g, %g})\n", e
, e
->type
, e
->name
, e
->arg1
, e
->arg2
, e
->retval
);
76 if (MSVCRT_default_matherr_func
)
78 ret
= MSVCRT_default_matherr_func(e
);
85 *MSVCRT__errno() = MSVCRT_EDOM
;
89 *MSVCRT__errno() = MSVCRT_ERANGE
;
95 ERR("Unhandled math error!\n");
101 /*********************************************************************
102 * __setusermatherr (MSVCRT.@)
104 void CDECL
MSVCRT___setusermatherr(MSVCRT_matherr_func func
)
106 MSVCRT_default_matherr_func
= func
;
107 TRACE("new matherr handler %p\n", func
);
110 static inline void math_error(int type
, const char *name
, double arg1
, double arg2
, double retval
)
112 struct MSVCRT__exception exception
= {type
, (char *)name
, arg1
, arg2
, retval
};
113 MSVCRT__matherr(&exception
);
116 /*********************************************************************
117 * _set_SSE2_enable (MSVCRT.@)
119 int CDECL
MSVCRT__set_SSE2_enable(int flag
)
121 sse2_enabled
= flag
&& sse2_supported
;
125 #if defined(_WIN64) && _MSVCR_VER>=120
126 /*********************************************************************
127 * _set_FMA3_enable (MSVCR120.@)
129 int CDECL
MSVCRT__set_FMA3_enable(int flag
)
131 FIXME("(%x) stub\n", flag
);
136 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || _MSVCR_VER>=120
138 /*********************************************************************
139 * _chgsignf (MSVCRT.@)
141 float CDECL
MSVCRT__chgsignf( float num
)
143 /* FIXME: +-infinity,Nan not tested */
147 /*********************************************************************
148 * _copysignf (MSVCRT.@)
150 float CDECL
MSVCRT__copysignf( float num
, float sign
)
153 return signbit(num
) ? num
: -num
;
154 return signbit(num
) ? -num
: num
;
157 /*********************************************************************
158 * _nextafterf (MSVCRT.@)
160 float CDECL
MSVCRT__nextafterf( float num
, float next
)
162 if (!finitef(num
) || !finitef(next
)) *MSVCRT__errno() = MSVCRT_EDOM
;
163 return nextafterf( num
, next
);
167 #if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__)
169 /*********************************************************************
170 * _finitef (MSVCRT.@)
172 int CDECL
MSVCRT__finitef( float num
)
174 return finitef(num
) != 0; /* See comment for _isnan() */
177 /*********************************************************************
180 INT CDECL
MSVCRT__isnanf( float num
)
182 /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
183 * Do the same, as the result may be used in calculations
185 return isnan(num
) != 0;
188 /*********************************************************************
191 float CDECL
MSVCRT__logbf( float num
)
193 float ret
= logbf(num
);
194 if (isnan(num
)) math_error(_DOMAIN
, "_logbf", num
, 0, ret
);
195 else if (!num
) math_error(_SING
, "_logbf", num
, 0, ret
);
199 /*********************************************************************
200 * MSVCRT_acosf (MSVCRT.@)
202 float CDECL
MSVCRT_acosf( float x
)
204 /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
205 * asin() uses a similar construction. This is bad because as x gets nearer to
206 * 1 the error in the expression "1 - x^2" can get relatively large due to
207 * cancellation. The sqrt() makes things worse. A safer way to calculate
208 * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
209 float ret
= atan2f(sqrtf((1 - x
) * (1 + x
)), x
);
210 if (x
< -1.0 || x
> 1.0 || !finitef(x
)) math_error(_DOMAIN
, "acosf", x
, 0, ret
);
214 /*********************************************************************
215 * MSVCRT_asinf (MSVCRT.@)
217 float CDECL
MSVCRT_asinf( float x
)
219 float ret
= atan2f(x
, sqrtf((1 - x
) * (1 + x
)));
220 if (x
< -1.0 || x
> 1.0 || !finitef(x
)) math_error(_DOMAIN
, "asinf", x
, 0, ret
);
224 /*********************************************************************
225 * MSVCRT_atanf (MSVCRT.@)
227 float CDECL
MSVCRT_atanf( float x
)
229 float ret
= atanf(x
);
230 if (!finitef(x
)) math_error(_DOMAIN
, "atanf", x
, 0, ret
);
234 /*********************************************************************
235 * MSVCRT_atan2f (MSVCRT.@)
237 float CDECL
MSVCRT_atan2f( float x
, float y
)
239 float ret
= atan2f(x
, y
);
240 if (isnan(x
)) math_error(_DOMAIN
, "atan2f", x
, y
, ret
);
244 /*********************************************************************
245 * MSVCRT_cosf (MSVCRT.@)
247 float CDECL
MSVCRT_cosf( float x
)
250 if (!finitef(x
)) math_error(_DOMAIN
, "cosf", x
, 0, ret
);
254 /*********************************************************************
255 * MSVCRT_coshf (MSVCRT.@)
257 float CDECL
MSVCRT_coshf( float x
)
259 float ret
= coshf(x
);
260 if (isnan(x
)) math_error(_DOMAIN
, "coshf", x
, 0, ret
);
264 /*********************************************************************
265 * MSVCRT_expf (MSVCRT.@)
267 float CDECL
MSVCRT_expf( float x
)
270 if (isnan(x
)) math_error(_DOMAIN
, "expf", x
, 0, ret
);
271 else if (finitef(x
) && !ret
) math_error(_UNDERFLOW
, "expf", x
, 0, ret
);
272 else if (finitef(x
) && !finitef(ret
)) math_error(_OVERFLOW
, "expf", x
, 0, ret
);
276 /*********************************************************************
277 * MSVCRT_fmodf (MSVCRT.@)
279 float CDECL
MSVCRT_fmodf( float x
, float y
)
281 float ret
= fmodf(x
, y
);
282 if (!finitef(x
) || !finitef(y
)) math_error(_DOMAIN
, "fmodf", x
, 0, ret
);
286 /*********************************************************************
287 * MSVCRT_logf (MSVCRT.@)
289 float CDECL
MSVCRT_logf( float x
)
292 if (x
< 0.0) math_error(_DOMAIN
, "logf", x
, 0, ret
);
293 else if (x
== 0.0) math_error(_SING
, "logf", x
, 0, ret
);
297 /*********************************************************************
298 * MSVCRT_log10f (MSVCRT.@)
300 float CDECL
MSVCRT_log10f( float x
)
302 float ret
= log10f(x
);
303 if (x
< 0.0) math_error(_DOMAIN
, "log10f", x
, 0, ret
);
304 else if (x
== 0.0) math_error(_SING
, "log10f", x
, 0, ret
);
308 /*********************************************************************
309 * MSVCRT_powf (MSVCRT.@)
311 float CDECL
MSVCRT_powf( float x
, float y
)
314 if (x
< 0 && y
!= floorf(y
)) math_error(_DOMAIN
, "powf", x
, y
, z
);
315 else if (!x
&& finitef(y
) && y
< 0) math_error(_SING
, "powf", x
, y
, z
);
316 else if (finitef(x
) && finitef(y
) && !finitef(z
)) math_error(_OVERFLOW
, "powf", x
, y
, z
);
317 else if (x
&& finitef(x
) && finitef(y
) && !z
) math_error(_UNDERFLOW
, "powf", x
, y
, z
);
321 /*********************************************************************
322 * MSVCRT_sinf (MSVCRT.@)
324 float CDECL
MSVCRT_sinf( float x
)
327 if (!finitef(x
)) math_error(_DOMAIN
, "sinf", x
, 0, ret
);
331 /*********************************************************************
332 * MSVCRT_sinhf (MSVCRT.@)
334 float CDECL
MSVCRT_sinhf( float x
)
336 float ret
= sinhf(x
);
337 if (isnan(x
)) math_error(_DOMAIN
, "sinhf", x
, 0, ret
);
341 /*********************************************************************
342 * MSVCRT_sqrtf (MSVCRT.@)
344 float CDECL
MSVCRT_sqrtf( float x
)
346 float ret
= sqrtf(x
);
347 if (x
< 0.0) math_error(_DOMAIN
, "sqrtf", x
, 0, ret
);
351 /*********************************************************************
352 * MSVCRT_tanf (MSVCRT.@)
354 float CDECL
MSVCRT_tanf( float x
)
357 if (!finitef(x
)) math_error(_DOMAIN
, "tanf", x
, 0, ret
);
361 /*********************************************************************
362 * MSVCRT_tanhf (MSVCRT.@)
364 float CDECL
MSVCRT_tanhf( float x
)
366 float ret
= tanhf(x
);
367 if (!finitef(x
)) math_error(_DOMAIN
, "tanhf", x
, 0, ret
);
371 /*********************************************************************
374 float CDECL
MSVCRT_ceilf( float x
)
379 /*********************************************************************
382 float CDECL
MSVCRT_fabsf( float x
)
387 /*********************************************************************
390 float CDECL
MSVCRT_floorf( float x
)
395 /*********************************************************************
398 float CDECL
MSVCRT_frexpf( float x
, int *exp
)
400 return frexpf( x
, exp
);
403 /*********************************************************************
406 float CDECL
MSVCRT_modff( float x
, float *iptr
)
408 return modff( x
, iptr
);
413 /*********************************************************************
414 * MSVCRT_acos (MSVCRT.@)
416 double CDECL
MSVCRT_acos( double x
)
418 /* glibc implements acos() as the FPU equivalent of atan2(sqrt(1 - x ^ 2), x).
419 * asin() uses a similar construction. This is bad because as x gets nearer to
420 * 1 the error in the expression "1 - x^2" can get relatively large due to
421 * cancellation. The sqrt() makes things worse. A safer way to calculate
422 * acos() is to use atan2(sqrt((1 - x) * (1 + x)), x). */
423 double ret
= atan2(sqrt((1 - x
) * (1 + x
)), x
);
424 if (x
< -1.0 || x
> 1.0 || !isfinite(x
)) math_error(_DOMAIN
, "acos", x
, 0, ret
);
428 /*********************************************************************
429 * MSVCRT_asin (MSVCRT.@)
431 double CDECL
MSVCRT_asin( double x
)
433 double ret
= atan2(x
, sqrt((1 - x
) * (1 + x
)));
434 if (x
< -1.0 || x
> 1.0 || !isfinite(x
)) math_error(_DOMAIN
, "asin", x
, 0, ret
);
438 /*********************************************************************
439 * MSVCRT_atan (MSVCRT.@)
441 double CDECL
MSVCRT_atan( double x
)
443 double ret
= atan(x
);
444 if (isnan(x
)) math_error(_DOMAIN
, "atan", x
, 0, ret
);
448 /*********************************************************************
449 * MSVCRT_atan2 (MSVCRT.@)
451 double CDECL
MSVCRT_atan2( double x
, double y
)
453 double ret
= atan2(x
, y
);
454 if (isnan(x
)) math_error(_DOMAIN
, "atan2", x
, y
, ret
);
458 /*********************************************************************
459 * MSVCRT_cos (MSVCRT.@)
461 double CDECL
MSVCRT_cos( double x
)
464 if (!isfinite(x
)) math_error(_DOMAIN
, "cos", x
, 0, ret
);
468 /*********************************************************************
469 * MSVCRT_cosh (MSVCRT.@)
471 double CDECL
MSVCRT_cosh( double x
)
473 double ret
= cosh(x
);
474 if (isnan(x
)) math_error(_DOMAIN
, "cosh", x
, 0, ret
);
478 /*********************************************************************
479 * MSVCRT_exp (MSVCRT.@)
481 double CDECL
MSVCRT_exp( double x
)
484 if (isnan(x
)) math_error(_DOMAIN
, "exp", x
, 0, ret
);
485 else if (isfinite(x
) && !ret
) math_error(_UNDERFLOW
, "exp", x
, 0, ret
);
486 else if (isfinite(x
) && !isfinite(ret
)) math_error(_OVERFLOW
, "exp", x
, 0, ret
);
490 /*********************************************************************
491 * MSVCRT_fmod (MSVCRT.@)
493 double CDECL
MSVCRT_fmod( double x
, double y
)
495 double ret
= fmod(x
, y
);
496 if (!isfinite(x
) || !isfinite(y
)) math_error(_DOMAIN
, "fmod", x
, y
, ret
);
500 /*********************************************************************
501 * MSVCRT_log (MSVCRT.@)
503 double CDECL
MSVCRT_log( double x
)
506 if (x
< 0.0) math_error(_DOMAIN
, "log", x
, 0, ret
);
507 else if (x
== 0.0) math_error(_SING
, "log", x
, 0, ret
);
511 /*********************************************************************
512 * MSVCRT_log10 (MSVCRT.@)
514 double CDECL
MSVCRT_log10( double x
)
516 double ret
= log10(x
);
517 if (x
< 0.0) math_error(_DOMAIN
, "log10", x
, 0, ret
);
518 else if (x
== 0.0) math_error(_SING
, "log10", x
, 0, ret
);
522 /*********************************************************************
523 * MSVCRT_pow (MSVCRT.@)
525 double CDECL
MSVCRT_pow( double x
, double y
)
528 if (x
< 0 && y
!= floor(y
)) math_error(_DOMAIN
, "pow", x
, y
, z
);
529 else if (!x
&& isfinite(y
) && y
< 0) math_error(_SING
, "pow", x
, y
, z
);
530 else if (isfinite(x
) && isfinite(y
) && !isfinite(z
)) math_error(_OVERFLOW
, "pow", x
, y
, z
);
531 else if (x
&& isfinite(x
) && isfinite(y
) && !z
) math_error(_UNDERFLOW
, "pow", x
, y
, z
);
535 /*********************************************************************
536 * MSVCRT_sin (MSVCRT.@)
538 double CDECL
MSVCRT_sin( double x
)
541 if (!isfinite(x
)) math_error(_DOMAIN
, "sin", x
, 0, ret
);
545 /*********************************************************************
546 * MSVCRT_sinh (MSVCRT.@)
548 double CDECL
MSVCRT_sinh( double x
)
550 double ret
= sinh(x
);
551 if (isnan(x
)) math_error(_DOMAIN
, "sinh", x
, 0, ret
);
555 /*********************************************************************
556 * MSVCRT_sqrt (MSVCRT.@)
558 double CDECL
MSVCRT_sqrt( double x
)
560 double ret
= sqrt(x
);
561 if (x
< 0.0) math_error(_DOMAIN
, "sqrt", x
, 0, ret
);
565 /*********************************************************************
566 * MSVCRT_tan (MSVCRT.@)
568 double CDECL
MSVCRT_tan( double x
)
571 if (!isfinite(x
)) math_error(_DOMAIN
, "tan", x
, 0, ret
);
575 /*********************************************************************
576 * MSVCRT_tanh (MSVCRT.@)
578 double CDECL
MSVCRT_tanh( double x
)
580 double ret
= tanh(x
);
581 if (isnan(x
)) math_error(_DOMAIN
, "tanh", x
, 0, ret
);
586 #if defined(__GNUC__) && defined(__i386__)
588 #define CREATE_FPU_FUNC1(name, call) \
589 __ASM_GLOBAL_FUNC(name, \
591 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
592 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
593 "movl %esp, %ebp\n\t" \
594 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
595 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
596 "fstpl (%esp)\n\t" /* store function argument */ \
598 "movl $1, %ecx\n\t" /* empty FPU stack */ \
602 "and $0x4500, %ax\n\t" \
603 "cmp $0x4100, %ax\n\t" \
605 "fstpl (%esp,%ecx,8)\n\t" \
610 "movl %ecx, -4(%ebp)\n\t" \
611 "call " __ASM_NAME( #call ) "\n\t" \
612 "movl -4(%ebp), %ecx\n\t" \
613 "fstpl (%esp)\n\t" /* save result */ \
614 "3:\n\t" /* restore FPU stack */ \
616 "fldl (%esp,%ecx,8)\n\t" \
617 "cmpl $0, %ecx\n\t" \
620 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
621 __ASM_CFI(".cfi_same_value %ebp\n\t") \
624 #define CREATE_FPU_FUNC2(name, call) \
625 __ASM_GLOBAL_FUNC(name, \
627 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
628 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
629 "movl %esp, %ebp\n\t" \
630 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
631 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
632 "fstpl 8(%esp)\n\t" /* store function argument */ \
636 "movl $2, %ecx\n\t" /* empty FPU stack */ \
640 "and $0x4500, %ax\n\t" \
641 "cmp $0x4100, %ax\n\t" \
643 "fstpl (%esp,%ecx,8)\n\t" \
648 "movl %ecx, -4(%ebp)\n\t" \
649 "call " __ASM_NAME( #call ) "\n\t" \
650 "movl -4(%ebp), %ecx\n\t" \
651 "fstpl 8(%esp)\n\t" /* save result */ \
652 "3:\n\t" /* restore FPU stack */ \
654 "fldl (%esp,%ecx,8)\n\t" \
655 "cmpl $1, %ecx\n\t" \
658 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
659 __ASM_CFI(".cfi_same_value %ebp\n\t") \
662 CREATE_FPU_FUNC1(_CIacos
, MSVCRT_acos
)
663 CREATE_FPU_FUNC1(_CIasin
, MSVCRT_asin
)
664 CREATE_FPU_FUNC1(_CIatan
, MSVCRT_atan
)
665 CREATE_FPU_FUNC2(_CIatan2
, MSVCRT_atan2
)
666 CREATE_FPU_FUNC1(_CIcos
, MSVCRT_cos
)
667 CREATE_FPU_FUNC1(_CIcosh
, MSVCRT_cosh
)
668 CREATE_FPU_FUNC1(_CIexp
, MSVCRT_exp
)
669 CREATE_FPU_FUNC2(_CIfmod
, MSVCRT_fmod
)
670 CREATE_FPU_FUNC1(_CIlog
, MSVCRT_log
)
671 CREATE_FPU_FUNC1(_CIlog10
, MSVCRT_log10
)
672 CREATE_FPU_FUNC2(_CIpow
, MSVCRT_pow
)
673 CREATE_FPU_FUNC1(_CIsin
, MSVCRT_sin
)
674 CREATE_FPU_FUNC1(_CIsinh
, MSVCRT_sinh
)
675 CREATE_FPU_FUNC1(_CIsqrt
, MSVCRT_sqrt
)
676 CREATE_FPU_FUNC1(_CItan
, MSVCRT_tan
)
677 CREATE_FPU_FUNC1(_CItanh
, MSVCRT_tanh
)
679 __ASM_GLOBAL_FUNC(MSVCRT__ftol
,
681 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
682 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
683 "movl %esp, %ebp\n\t"
684 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
685 "subl $12, %esp\n\t" /* sizeof(LONGLONG) + 2*sizeof(WORD) */
687 "mov (%esp), %ax\n\t"
689 "mov %ax, 2(%esp)\n\t"
693 "movl 4(%esp), %eax\n\t"
694 "movl 8(%esp), %edx\n\t"
696 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
697 __ASM_CFI(".cfi_same_value %ebp\n\t")
700 #endif /* defined(__GNUC__) && defined(__i386__) */
702 /*********************************************************************
703 * _fpclass (MSVCRT.@)
705 int CDECL
MSVCRT__fpclass(double num
)
707 #if defined(HAVE_FPCLASS) || defined(fpclass)
708 switch (fpclass( num
))
710 case FP_SNAN
: return MSVCRT__FPCLASS_SNAN
;
711 case FP_QNAN
: return MSVCRT__FPCLASS_QNAN
;
712 case FP_NINF
: return MSVCRT__FPCLASS_NINF
;
713 case FP_PINF
: return MSVCRT__FPCLASS_PINF
;
714 case FP_NDENORM
: return MSVCRT__FPCLASS_ND
;
715 case FP_PDENORM
: return MSVCRT__FPCLASS_PD
;
716 case FP_NZERO
: return MSVCRT__FPCLASS_NZ
;
717 case FP_PZERO
: return MSVCRT__FPCLASS_PZ
;
718 case FP_NNORM
: return MSVCRT__FPCLASS_NN
;
719 case FP_PNORM
: return MSVCRT__FPCLASS_PN
;
720 default: return MSVCRT__FPCLASS_PN
;
722 #elif defined (fpclassify)
723 switch (fpclassify( num
))
725 case FP_NAN
: return MSVCRT__FPCLASS_QNAN
;
726 case FP_INFINITE
: return signbit(num
) ? MSVCRT__FPCLASS_NINF
: MSVCRT__FPCLASS_PINF
;
727 case FP_SUBNORMAL
: return signbit(num
) ?MSVCRT__FPCLASS_ND
: MSVCRT__FPCLASS_PD
;
728 case FP_ZERO
: return signbit(num
) ? MSVCRT__FPCLASS_NZ
: MSVCRT__FPCLASS_PZ
;
730 return signbit(num
) ? MSVCRT__FPCLASS_NN
: MSVCRT__FPCLASS_PN
;
733 return MSVCRT__FPCLASS_QNAN
;
734 return num
== 0.0 ? MSVCRT__FPCLASS_PZ
: (num
< 0 ? MSVCRT__FPCLASS_NN
: MSVCRT__FPCLASS_PN
);
738 /*********************************************************************
741 unsigned int CDECL
_rotl(unsigned int num
, int shift
)
744 return (num
<< shift
) | (num
>> (32-shift
));
747 /*********************************************************************
750 MSVCRT_ulong CDECL
MSVCRT__lrotl(MSVCRT_ulong num
, int shift
)
753 return (num
<< shift
) | (num
>> (32-shift
));
756 /*********************************************************************
759 MSVCRT_ulong CDECL
MSVCRT__lrotr(MSVCRT_ulong num
, int shift
)
762 return (num
>> shift
) | (num
<< (32-shift
));
765 /*********************************************************************
768 unsigned int CDECL
_rotr(unsigned int num
, int shift
)
771 return (num
>> shift
) | (num
<< (32-shift
));
774 /*********************************************************************
777 unsigned __int64 CDECL
_rotl64(unsigned __int64 num
, int shift
)
780 return (num
<< shift
) | (num
>> (64-shift
));
783 /*********************************************************************
786 unsigned __int64 CDECL
_rotr64(unsigned __int64 num
, int shift
)
789 return (num
>> shift
) | (num
<< (64-shift
));
792 /*********************************************************************
795 int CDECL
MSVCRT_abs( int n
)
797 return n
>= 0 ? n
: -n
;
800 /*********************************************************************
803 MSVCRT_long CDECL
MSVCRT_labs( MSVCRT_long n
)
805 return n
>= 0 ? n
: -n
;
809 /*********************************************************************
812 MSVCRT_longlong CDECL
MSVCRT_llabs( MSVCRT_longlong n
)
814 return n
>= 0 ? n
: -n
;
818 /*********************************************************************
821 __int64 CDECL
_abs64( __int64 n
)
823 return n
>= 0 ? n
: -n
;
826 /*********************************************************************
829 double CDECL
MSVCRT__logb(double num
)
831 double ret
= logb(num
);
832 if (isnan(num
)) math_error(_DOMAIN
, "_logb", num
, 0, ret
);
833 else if (!num
) math_error(_SING
, "_logb", num
, 0, ret
);
837 /*********************************************************************
840 double CDECL
_hypot(double x
, double y
)
842 /* FIXME: errno handling */
843 return hypot( x
, y
);
846 /*********************************************************************
849 float CDECL
MSVCRT__hypotf(float x
, float y
)
851 /* FIXME: errno handling */
852 return hypotf( x
, y
);
855 /*********************************************************************
858 double CDECL
MSVCRT_ceil( double x
)
863 /*********************************************************************
866 double CDECL
MSVCRT_floor( double x
)
871 /*********************************************************************
874 double CDECL
MSVCRT_fabs( double x
)
879 /*********************************************************************
882 double CDECL
MSVCRT_frexp( double x
, int *exp
)
884 return frexp( x
, exp
);
887 /*********************************************************************
890 double CDECL
MSVCRT_modf( double x
, double *iptr
)
892 return modf( x
, iptr
);
895 /**********************************************************************
896 * _statusfp2 (MSVCRT.@)
898 * Not exported by native msvcrt, added in msvcr80.
900 #if defined(__i386__) || defined(__x86_64__)
901 void CDECL
_statusfp2( unsigned int *x86_sw
, unsigned int *sse2_sw
)
905 unsigned long fpword
;
909 __asm__
__volatile__( "fstsw %0" : "=m" (fpword
) );
911 if (fpword
& 0x1) flags
|= MSVCRT__SW_INVALID
;
912 if (fpword
& 0x2) flags
|= MSVCRT__SW_DENORMAL
;
913 if (fpword
& 0x4) flags
|= MSVCRT__SW_ZERODIVIDE
;
914 if (fpword
& 0x8) flags
|= MSVCRT__SW_OVERFLOW
;
915 if (fpword
& 0x10) flags
|= MSVCRT__SW_UNDERFLOW
;
916 if (fpword
& 0x20) flags
|= MSVCRT__SW_INEXACT
;
920 if (!sse2_sw
) return;
924 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
926 if (fpword
& 0x1) flags
|= MSVCRT__SW_INVALID
;
927 if (fpword
& 0x2) flags
|= MSVCRT__SW_DENORMAL
;
928 if (fpword
& 0x4) flags
|= MSVCRT__SW_ZERODIVIDE
;
929 if (fpword
& 0x8) flags
|= MSVCRT__SW_OVERFLOW
;
930 if (fpword
& 0x10) flags
|= MSVCRT__SW_UNDERFLOW
;
931 if (fpword
& 0x20) flags
|= MSVCRT__SW_INEXACT
;
936 FIXME( "not implemented\n" );
941 /**********************************************************************
942 * _statusfp (MSVCRT.@)
944 unsigned int CDECL
_statusfp(void)
946 #if defined(__i386__) || defined(__x86_64__)
947 unsigned int x86_sw
, sse2_sw
;
949 _statusfp2( &x86_sw
, &sse2_sw
);
950 /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
951 return x86_sw
| sse2_sw
;
953 FIXME( "not implemented\n" );
958 /*********************************************************************
959 * _clearfp (MSVCRT.@)
961 unsigned int CDECL
_clearfp(void)
963 unsigned int flags
= 0;
964 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
965 unsigned long fpword
;
967 __asm__
__volatile__( "fnstsw %0; fnclex" : "=m" (fpword
) );
968 if (fpword
& 0x1) flags
|= MSVCRT__SW_INVALID
;
969 if (fpword
& 0x2) flags
|= MSVCRT__SW_DENORMAL
;
970 if (fpword
& 0x4) flags
|= MSVCRT__SW_ZERODIVIDE
;
971 if (fpword
& 0x8) flags
|= MSVCRT__SW_OVERFLOW
;
972 if (fpword
& 0x10) flags
|= MSVCRT__SW_UNDERFLOW
;
973 if (fpword
& 0x20) flags
|= MSVCRT__SW_INEXACT
;
977 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
978 if (fpword
& 0x1) flags
|= MSVCRT__SW_INVALID
;
979 if (fpword
& 0x2) flags
|= MSVCRT__SW_DENORMAL
;
980 if (fpword
& 0x4) flags
|= MSVCRT__SW_ZERODIVIDE
;
981 if (fpword
& 0x8) flags
|= MSVCRT__SW_OVERFLOW
;
982 if (fpword
& 0x10) flags
|= MSVCRT__SW_UNDERFLOW
;
983 if (fpword
& 0x20) flags
|= MSVCRT__SW_INEXACT
;
985 __asm__
__volatile__( "ldmxcsr %0" : : "m" (fpword
) );
988 FIXME( "not implemented\n" );
993 /*********************************************************************
994 * __fpecode (MSVCRT.@)
996 int * CDECL
__fpecode(void)
998 return &msvcrt_get_thread_data()->fpecode
;
1001 /*********************************************************************
1004 double CDECL
MSVCRT_ldexp(double num
, MSVCRT_long exp
)
1006 double z
= ldexp(num
,exp
);
1008 if (isfinite(num
) && !isfinite(z
))
1009 math_error(_OVERFLOW
, "ldexp", num
, exp
, z
);
1010 else if (num
&& isfinite(num
) && !z
)
1011 math_error(_UNDERFLOW
, "ldexp", num
, exp
, z
);
1012 else if (z
== 0 && signbit(z
))
1013 z
= 0.0; /* Convert -0 -> +0 */
1017 /*********************************************************************
1020 double CDECL
MSVCRT__cabs(struct MSVCRT__complex num
)
1022 return sqrt(num
.x
* num
.x
+ num
.y
* num
.y
);
1025 /*********************************************************************
1026 * _chgsign (MSVCRT.@)
1028 double CDECL
MSVCRT__chgsign(double num
)
1030 /* FIXME: +-infinity,Nan not tested */
1034 /*********************************************************************
1035 * __control87_2 (MSVCR80.@)
1037 * Not exported by native msvcrt, added in msvcr80.
1039 #if defined(__i386__) || defined(__x86_64__)
1040 int CDECL
__control87_2( unsigned int newval
, unsigned int mask
,
1041 unsigned int *x86_cw
, unsigned int *sse2_cw
)
1044 unsigned long fpword
;
1049 __asm__
__volatile__( "fstcw %0" : "=m" (fpword
) );
1051 /* Convert into mask constants */
1053 if (fpword
& 0x1) flags
|= MSVCRT__EM_INVALID
;
1054 if (fpword
& 0x2) flags
|= MSVCRT__EM_DENORMAL
;
1055 if (fpword
& 0x4) flags
|= MSVCRT__EM_ZERODIVIDE
;
1056 if (fpword
& 0x8) flags
|= MSVCRT__EM_OVERFLOW
;
1057 if (fpword
& 0x10) flags
|= MSVCRT__EM_UNDERFLOW
;
1058 if (fpword
& 0x20) flags
|= MSVCRT__EM_INEXACT
;
1059 switch (fpword
& 0xc00)
1061 case 0xc00: flags
|= MSVCRT__RC_UP
|MSVCRT__RC_DOWN
; break;
1062 case 0x800: flags
|= MSVCRT__RC_UP
; break;
1063 case 0x400: flags
|= MSVCRT__RC_DOWN
; break;
1065 switch (fpword
& 0x300)
1067 case 0x0: flags
|= MSVCRT__PC_24
; break;
1068 case 0x200: flags
|= MSVCRT__PC_53
; break;
1069 case 0x300: flags
|= MSVCRT__PC_64
; break;
1071 if (fpword
& 0x1000) flags
|= MSVCRT__IC_AFFINE
;
1073 TRACE( "x86 flags=%08x newval=%08x mask=%08x\n", flags
, newval
, mask
);
1076 flags
= (flags
& ~mask
) | (newval
& mask
);
1078 /* Convert (masked) value back to fp word */
1080 if (flags
& MSVCRT__EM_INVALID
) fpword
|= 0x1;
1081 if (flags
& MSVCRT__EM_DENORMAL
) fpword
|= 0x2;
1082 if (flags
& MSVCRT__EM_ZERODIVIDE
) fpword
|= 0x4;
1083 if (flags
& MSVCRT__EM_OVERFLOW
) fpword
|= 0x8;
1084 if (flags
& MSVCRT__EM_UNDERFLOW
) fpword
|= 0x10;
1085 if (flags
& MSVCRT__EM_INEXACT
) fpword
|= 0x20;
1086 switch (flags
& MSVCRT__MCW_RC
)
1088 case MSVCRT__RC_UP
|MSVCRT__RC_DOWN
: fpword
|= 0xc00; break;
1089 case MSVCRT__RC_UP
: fpword
|= 0x800; break;
1090 case MSVCRT__RC_DOWN
: fpword
|= 0x400; break;
1092 switch (flags
& MSVCRT__MCW_PC
)
1094 case MSVCRT__PC_64
: fpword
|= 0x300; break;
1095 case MSVCRT__PC_53
: fpword
|= 0x200; break;
1096 case MSVCRT__PC_24
: fpword
|= 0x0; break;
1098 if (flags
& MSVCRT__IC_AFFINE
) fpword
|= 0x1000;
1100 __asm__
__volatile__( "fldcw %0" : : "m" (fpword
) );
1105 if (!sse2_cw
) return 1;
1109 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
1111 /* Convert into mask constants */
1113 if (fpword
& 0x80) flags
|= MSVCRT__EM_INVALID
;
1114 if (fpword
& 0x100) flags
|= MSVCRT__EM_DENORMAL
;
1115 if (fpword
& 0x200) flags
|= MSVCRT__EM_ZERODIVIDE
;
1116 if (fpword
& 0x400) flags
|= MSVCRT__EM_OVERFLOW
;
1117 if (fpword
& 0x800) flags
|= MSVCRT__EM_UNDERFLOW
;
1118 if (fpword
& 0x1000) flags
|= MSVCRT__EM_INEXACT
;
1119 switch (fpword
& 0x6000)
1121 case 0x6000: flags
|= MSVCRT__RC_UP
|MSVCRT__RC_DOWN
; break;
1122 case 0x4000: flags
|= MSVCRT__RC_UP
; break;
1123 case 0x2000: flags
|= MSVCRT__RC_DOWN
; break;
1125 switch (fpword
& 0x8040)
1127 case 0x0040: flags
|= MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS
; break;
1128 case 0x8000: flags
|= MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS
; break;
1129 case 0x8040: flags
|= MSVCRT__DN_FLUSH
; break;
1132 TRACE( "sse2 flags=%08x newval=%08x mask=%08x\n", flags
, newval
, mask
);
1135 flags
= (flags
& ~mask
) | (newval
& mask
);
1137 /* Convert (masked) value back to fp word */
1139 if (flags
& MSVCRT__EM_INVALID
) fpword
|= 0x80;
1140 if (flags
& MSVCRT__EM_DENORMAL
) fpword
|= 0x100;
1141 if (flags
& MSVCRT__EM_ZERODIVIDE
) fpword
|= 0x200;
1142 if (flags
& MSVCRT__EM_OVERFLOW
) fpword
|= 0x400;
1143 if (flags
& MSVCRT__EM_UNDERFLOW
) fpword
|= 0x800;
1144 if (flags
& MSVCRT__EM_INEXACT
) fpword
|= 0x1000;
1145 switch (flags
& MSVCRT__MCW_RC
)
1147 case MSVCRT__RC_UP
|MSVCRT__RC_DOWN
: fpword
|= 0x6000; break;
1148 case MSVCRT__RC_UP
: fpword
|= 0x4000; break;
1149 case MSVCRT__RC_DOWN
: fpword
|= 0x2000; break;
1151 switch (flags
& MSVCRT__MCW_DN
)
1153 case MSVCRT__DN_FLUSH_OPERANDS_SAVE_RESULTS
: fpword
|= 0x0040; break;
1154 case MSVCRT__DN_SAVE_OPERANDS_FLUSH_RESULTS
: fpword
|= 0x8000; break;
1155 case MSVCRT__DN_FLUSH
: fpword
|= 0x8040; break;
1157 __asm__
__volatile__( "ldmxcsr %0" : : "m" (fpword
) );
1165 FIXME( "not implemented\n" );
1171 /*********************************************************************
1172 * _control87 (MSVCRT.@)
1174 unsigned int CDECL
_control87(unsigned int newval
, unsigned int mask
)
1176 #if defined(__i386__) || defined(__x86_64__)
1177 unsigned int x86_cw
, sse2_cw
;
1179 __control87_2( newval
, mask
, &x86_cw
, &sse2_cw
);
1181 if ((x86_cw
^ sse2_cw
) & (MSVCRT__MCW_EM
| MSVCRT__MCW_RC
)) x86_cw
|= MSVCRT__EM_AMBIGUOUS
;
1184 FIXME( "not implemented\n" );
1189 /*********************************************************************
1190 * _controlfp (MSVCRT.@)
1192 unsigned int CDECL
_controlfp(unsigned int newval
, unsigned int mask
)
1194 return _control87( newval
, mask
& ~MSVCRT__EM_DENORMAL
);
1197 /*********************************************************************
1198 * _set_controlfp (MSVCRT.@)
1200 void CDECL
_set_controlfp( unsigned int newval
, unsigned int mask
)
1202 _controlfp( newval
, mask
);
1205 /*********************************************************************
1206 * _controlfp_s (MSVCRT.@)
1208 int CDECL
_controlfp_s(unsigned int *cur
, unsigned int newval
, unsigned int mask
)
1210 static const unsigned int all_flags
= (MSVCRT__MCW_EM
| MSVCRT__MCW_IC
| MSVCRT__MCW_RC
|
1211 MSVCRT__MCW_PC
| MSVCRT__MCW_DN
);
1214 if (!MSVCRT_CHECK_PMT( !(newval
& mask
& ~all_flags
) ))
1216 if (cur
) *cur
= _controlfp( 0, 0 ); /* retrieve it anyway */
1217 return MSVCRT_EINVAL
;
1219 val
= _controlfp( newval
, mask
);
1220 if (cur
) *cur
= val
;
1225 /*********************************************************************
1226 * fegetenv (MSVCR120.@)
1228 int CDECL
MSVCRT_fegetenv(MSVCRT_fenv_t
*env
)
1230 env
->control
= _controlfp(0, 0) & (MSVCRT__EM_INEXACT
| MSVCRT__EM_UNDERFLOW
|
1231 MSVCRT__EM_OVERFLOW
| MSVCRT__EM_ZERODIVIDE
| MSVCRT__EM_INVALID
);
1232 env
->status
= _statusfp();
1238 /*********************************************************************
1239 * __fpe_flt_rounds (UCRTBASE.@)
1241 int CDECL
__fpe_flt_rounds(void)
1243 unsigned int fpc
= _controlfp(0, 0) & MSVCRT__RC_CHOP
;
1248 case MSVCRT__RC_CHOP
: return 0;
1249 case MSVCRT__RC_NEAR
: return 1;
1251 case MSVCRT__RC_UP
: return 3;
1254 case MSVCRT__RC_UP
: return 2;
1263 /*********************************************************************
1264 * fegetround (MSVCR120.@)
1266 int CDECL
MSVCRT_fegetround(void)
1268 return _controlfp(0, 0) & MSVCRT__RC_CHOP
;
1271 /*********************************************************************
1272 * fesetround (MSVCR120.@)
1274 int CDECL
MSVCRT_fesetround(int round_mode
)
1276 if (round_mode
& (~MSVCRT__RC_CHOP
))
1278 _controlfp(round_mode
, MSVCRT__RC_CHOP
);
1282 #endif /* _MSVCR_VER>=120 */
1284 /*********************************************************************
1285 * _copysign (MSVCRT.@)
1287 double CDECL
MSVCRT__copysign(double num
, double sign
)
1290 return signbit(num
) ? num
: -num
;
1291 return signbit(num
) ? -num
: num
;
1294 /*********************************************************************
1295 * _finite (MSVCRT.@)
1297 int CDECL
MSVCRT__finite(double num
)
1299 return isfinite(num
) != 0; /* See comment for _isnan() */
1302 /*********************************************************************
1303 * _fpreset (MSVCRT.@)
1305 void CDECL
_fpreset(void)
1307 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1308 const unsigned int x86_cw
= 0x27f;
1309 __asm__
__volatile__( "fninit; fldcw %0" : : "m" (x86_cw
) );
1312 const unsigned long sse2_cw
= 0x1f80;
1313 __asm__
__volatile__( "ldmxcsr %0" : : "m" (sse2_cw
) );
1316 FIXME( "not implemented\n" );
1321 /*********************************************************************
1322 * fesetenv (MSVCR120.@)
1324 int CDECL
MSVCRT_fesetenv(const MSVCRT_fenv_t
*env
)
1326 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
1334 DWORD instruction_pointer
;
1342 TRACE( "(%p)\n", env
);
1344 if (!env
->control
&& !env
->status
) {
1349 __asm__
__volatile__( "fnstenv %0" : "=m" (fenv
) );
1351 fenv
.control_word
&= ~0x3d;
1352 if (env
->control
& MSVCRT__EM_INVALID
) fenv
.control_word
|= 0x1;
1353 if (env
->control
& MSVCRT__EM_ZERODIVIDE
) fenv
.control_word
|= 0x4;
1354 if (env
->control
& MSVCRT__EM_OVERFLOW
) fenv
.control_word
|= 0x8;
1355 if (env
->control
& MSVCRT__EM_UNDERFLOW
) fenv
.control_word
|= 0x10;
1356 if (env
->control
& MSVCRT__EM_INEXACT
) fenv
.control_word
|= 0x20;
1358 fenv
.status_word
&= ~0x3d;
1359 if (env
->status
& MSVCRT__SW_INVALID
) fenv
.status_word
|= 0x1;
1360 if (env
->status
& MSVCRT__SW_ZERODIVIDE
) fenv
.status_word
|= 0x4;
1361 if (env
->status
& MSVCRT__SW_OVERFLOW
) fenv
.status_word
|= 0x8;
1362 if (env
->status
& MSVCRT__SW_UNDERFLOW
) fenv
.status_word
|= 0x10;
1363 if (env
->status
& MSVCRT__SW_INEXACT
) fenv
.status_word
|= 0x20;
1365 __asm__
__volatile__( "fldenv %0" : : "m" (fenv
) : "st", "st(1)",
1366 "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
1372 __asm__
__volatile__( "stmxcsr %0" : "=m" (fpword
) );
1374 if (env
->control
& MSVCRT__EM_INVALID
) fpword
|= 0x80;
1375 if (env
->control
& MSVCRT__EM_ZERODIVIDE
) fpword
|= 0x200;
1376 if (env
->control
& MSVCRT__EM_OVERFLOW
) fpword
|= 0x400;
1377 if (env
->control
& MSVCRT__EM_UNDERFLOW
) fpword
|= 0x800;
1378 if (env
->control
& MSVCRT__EM_INEXACT
) fpword
|= 0x1000;
1379 __asm__
__volatile__( "ldmxcsr %0" : : "m" (fpword
) );
1384 FIXME( "not implemented\n" );
1390 /*********************************************************************
1393 INT CDECL
MSVCRT__isnan(double num
)
1395 /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
1396 * Do the same, as the result may be used in calculations
1398 return isnan(num
) != 0;
1401 /*********************************************************************
1404 double CDECL
MSVCRT__j0(double num
)
1406 /* FIXME: errno handling */
1410 FIXME("not implemented\n");
1415 /*********************************************************************
1418 double CDECL
MSVCRT__j1(double num
)
1420 /* FIXME: errno handling */
1424 FIXME("not implemented\n");
1429 /*********************************************************************
1432 double CDECL
MSVCRT__jn(int n
, double num
)
1434 /* FIXME: errno handling */
1438 FIXME("not implemented\n");
1443 /*********************************************************************
1446 double CDECL
MSVCRT__y0(double num
)
1449 if (!isfinite(num
)) *MSVCRT__errno() = MSVCRT_EDOM
;
1452 if (MSVCRT__fpclass(retval
) == MSVCRT__FPCLASS_NINF
)
1454 *MSVCRT__errno() = MSVCRT_EDOM
;
1458 FIXME("not implemented\n");
1464 /*********************************************************************
1467 double CDECL
MSVCRT__y1(double num
)
1470 if (!isfinite(num
)) *MSVCRT__errno() = MSVCRT_EDOM
;
1473 if (MSVCRT__fpclass(retval
) == MSVCRT__FPCLASS_NINF
)
1475 *MSVCRT__errno() = MSVCRT_EDOM
;
1479 FIXME("not implemented\n");
1485 /*********************************************************************
1488 double CDECL
MSVCRT__yn(int order
, double num
)
1491 if (!isfinite(num
)) *MSVCRT__errno() = MSVCRT_EDOM
;
1493 retval
= yn(order
,num
);
1494 if (MSVCRT__fpclass(retval
) == MSVCRT__FPCLASS_NINF
)
1496 *MSVCRT__errno() = MSVCRT_EDOM
;
1500 FIXME("not implemented\n");
1508 /*********************************************************************
1509 * _nearbyint (MSVCR120.@)
1511 double CDECL
MSVCRT_nearbyint(double num
)
1513 #ifdef HAVE_NEARBYINT
1514 return nearbyint(num
);
1516 return num
>= 0 ? floor(num
+ 0.5) : ceil(num
- 0.5);
1520 /*********************************************************************
1521 * _nearbyintf (MSVCR120.@)
1523 float CDECL
MSVCRT_nearbyintf(float num
)
1525 #ifdef HAVE_NEARBYINTF
1526 return nearbyintf(num
);
1528 return MSVCRT_nearbyint(num
);
1532 #endif /* _MSVCR_VER>=120 */
1534 /*********************************************************************
1535 * _nextafter (MSVCRT.@)
1537 double CDECL
MSVCRT__nextafter(double num
, double next
)
1540 if (!isfinite(num
) || !isfinite(next
)) *MSVCRT__errno() = MSVCRT_EDOM
;
1541 retval
= nextafter(num
,next
);
1545 /*********************************************************************
1548 char * CDECL
MSVCRT__ecvt( double number
, int ndigits
, int *decpt
, int *sign
)
1551 thread_data_t
*data
= msvcrt_get_thread_data();
1552 /* FIXME: check better for overflow (native supports over 300 chars) */
1553 ndigits
= min( ndigits
, 80 - 7); /* 7 : space for dec point, 1 for "e",
1554 * 4 for exponent and one for
1555 * terminating '\0' */
1556 if (!data
->efcvt_buffer
)
1557 data
->efcvt_buffer
= MSVCRT_malloc( 80 ); /* ought to be enough */
1564 /* handle cases with zero ndigits or less */
1566 if( prec
< 1) prec
= 2;
1567 len
= snprintf(data
->efcvt_buffer
, 80, "%.*le", prec
- 1, number
);
1568 /* take the decimal "point away */
1570 memmove( data
->efcvt_buffer
+ 1, data
->efcvt_buffer
+ 2, len
- 1 );
1571 /* take the exponential "e" out */
1572 data
->efcvt_buffer
[ prec
] = '\0';
1573 /* read the exponent */
1574 sscanf( data
->efcvt_buffer
+ prec
+ 1, "%d", decpt
);
1576 /* adjust for some border cases */
1577 if( data
->efcvt_buffer
[0] == '0')/* value is zero */
1579 /* handle cases with zero ndigits or less */
1581 if( data
->efcvt_buffer
[ 0] >= '5')
1583 data
->efcvt_buffer
[ 0] = '\0';
1585 TRACE("out=\"%s\"\n",data
->efcvt_buffer
);
1586 return data
->efcvt_buffer
;
1589 /*********************************************************************
1590 * _ecvt_s (MSVCRT.@)
1592 int CDECL
MSVCRT__ecvt_s( char *buffer
, MSVCRT_size_t length
, double number
, int ndigits
, int *decpt
, int *sign
)
1596 const char infret
[] = "1#INF";
1598 if (!MSVCRT_CHECK_PMT(buffer
!= NULL
)) return MSVCRT_EINVAL
;
1599 if (!MSVCRT_CHECK_PMT(decpt
!= NULL
)) return MSVCRT_EINVAL
;
1600 if (!MSVCRT_CHECK_PMT(sign
!= NULL
)) return MSVCRT_EINVAL
;
1601 if (!MSVCRT_CHECK_PMT_ERR( length
> 2, MSVCRT_ERANGE
)) return MSVCRT_ERANGE
;
1602 if (!MSVCRT_CHECK_PMT_ERR(ndigits
< (int)length
- 1, MSVCRT_ERANGE
)) return MSVCRT_ERANGE
;
1604 /* special case - inf */
1605 if(number
== HUGE_VAL
|| number
== -HUGE_VAL
)
1607 memset(buffer
, '0', ndigits
);
1608 memcpy(buffer
, infret
, min(ndigits
, sizeof(infret
) - 1 ) );
1609 buffer
[ndigits
] = '\0';
1611 if(number
== -HUGE_VAL
)
1617 /* handle cases with zero ndigits or less */
1619 if( prec
< 1) prec
= 2;
1620 result
= MSVCRT_malloc(prec
+ 7);
1627 len
= snprintf(result
, prec
+ 7, "%.*le", prec
- 1, number
);
1628 /* take the decimal "point away */
1630 memmove( result
+ 1, result
+ 2, len
- 1 );
1631 /* take the exponential "e" out */
1632 result
[ prec
] = '\0';
1633 /* read the exponent */
1634 sscanf( result
+ prec
+ 1, "%d", decpt
);
1636 /* adjust for some border cases */
1637 if( result
[0] == '0')/* value is zero */
1639 /* handle cases with zero ndigits or less */
1641 if( result
[ 0] >= '5')
1645 memcpy( buffer
, result
, max(ndigits
+ 1, 1) );
1646 MSVCRT_free( result
);
1650 /***********************************************************************
1653 char * CDECL
MSVCRT__fcvt( double number
, int ndigits
, int *decpt
, int *sign
)
1655 thread_data_t
*data
= msvcrt_get_thread_data();
1656 int stop
, dec1
, dec2
;
1657 char *ptr1
, *ptr2
, *first
;
1658 char buf
[80]; /* ought to be enough */
1660 if (!data
->efcvt_buffer
)
1661 data
->efcvt_buffer
= MSVCRT_malloc( 80 ); /* ought to be enough */
1669 stop
= snprintf(buf
, 80, "%.*f", ndigits
< 0 ? 0 : ndigits
, number
);
1671 ptr2
= data
->efcvt_buffer
;
1676 /* For numbers below the requested resolution, work out where
1677 the decimal point will be rather than finding it in the string */
1678 if (number
< 1.0 && number
> 0.0) {
1679 dec2
= log10(number
+ 1e-10);
1680 if (-dec2
<= ndigits
) dec2
= 0;
1683 /* If requested digits is zero or less, we will need to truncate
1684 * the returned string */
1689 while (*ptr1
== '0') ptr1
++; /* Skip leading zeroes */
1690 while (*ptr1
!= '\0' && *ptr1
!= '.') {
1691 if (!first
) first
= ptr2
;
1692 if ((ptr1
- buf
) < stop
) {
1703 while (*ptr1
== '0') { /* Process leading zeroes */
1708 while (*ptr1
!= '\0') {
1709 if (!first
) first
= ptr2
;
1716 /* We never found a non-zero digit, then our number is either
1717 * smaller than the requested precision, or 0.0 */
1722 first
= data
->efcvt_buffer
;
1727 *decpt
= dec2
? dec2
: dec1
;
1731 /***********************************************************************
1732 * _fcvt_s (MSVCRT.@)
1734 int CDECL
MSVCRT__fcvt_s(char* outbuffer
, MSVCRT_size_t size
, double number
, int ndigits
, int *decpt
, int *sign
)
1736 int stop
, dec1
, dec2
;
1737 char *ptr1
, *ptr2
, *first
;
1738 char buf
[80]; /* ought to be enough */
1740 if (!outbuffer
|| !decpt
|| !sign
|| size
== 0)
1742 *MSVCRT__errno() = MSVCRT_EINVAL
;
1743 return MSVCRT_EINVAL
;
1752 stop
= snprintf(buf
, 80, "%.*f", ndigits
< 0 ? 0 : ndigits
, number
);
1759 /* For numbers below the requested resolution, work out where
1760 the decimal point will be rather than finding it in the string */
1761 if (number
< 1.0 && number
> 0.0) {
1762 dec2
= log10(number
+ 1e-10);
1763 if (-dec2
<= ndigits
) dec2
= 0;
1766 /* If requested digits is zero or less, we will need to truncate
1767 * the returned string */
1772 while (*ptr1
== '0') ptr1
++; /* Skip leading zeroes */
1773 while (*ptr1
!= '\0' && *ptr1
!= '.') {
1774 if (!first
) first
= ptr2
;
1775 if ((ptr1
- buf
) < stop
) {
1789 while (*ptr1
== '0') { /* Process leading zeroes */
1790 if (number
== 0.0 && size
> 1) {
1798 while (*ptr1
!= '\0') {
1799 if (!first
) first
= ptr2
;
1809 /* We never found a non-zero digit, then our number is either
1810 * smaller than the requested precision, or 0.0 */
1811 if (!first
&& (number
<= 0.0))
1814 *decpt
= dec2
? dec2
: dec1
;
1818 /***********************************************************************
1821 char * CDECL
MSVCRT__gcvt( double number
, int ndigit
, char *buff
)
1824 *MSVCRT__errno() = MSVCRT_EINVAL
;
1829 *MSVCRT__errno() = MSVCRT_ERANGE
;
1833 MSVCRT_sprintf(buff
, "%.*g", ndigit
, number
);
1837 /***********************************************************************
1838 * _gcvt_s (MSVCRT.@)
1840 int CDECL
MSVCRT__gcvt_s(char *buff
, MSVCRT_size_t size
, double number
, int digits
)
1845 *MSVCRT__errno() = MSVCRT_EINVAL
;
1846 return MSVCRT_EINVAL
;
1849 if( digits
<0 || digits
>=size
) {
1853 *MSVCRT__errno() = MSVCRT_ERANGE
;
1854 return MSVCRT_ERANGE
;
1857 len
= MSVCRT__scprintf("%.*g", digits
, number
);
1860 *MSVCRT__errno() = MSVCRT_ERANGE
;
1861 return MSVCRT_ERANGE
;
1864 MSVCRT_sprintf(buff
, "%.*g", digits
, number
);
1868 #include <stdlib.h> /* div_t, ldiv_t */
1870 /*********************************************************************
1873 * [i386] Windows binary compatible - returns the struct in eax/edx.
1876 unsigned __int64 CDECL
MSVCRT_div(int num
, int denom
)
1878 div_t dt
= div(num
,denom
);
1879 return ((unsigned __int64
)dt
.rem
<< 32) | (unsigned int)dt
.quot
;
1882 /*********************************************************************
1885 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
1887 MSVCRT_div_t CDECL
MSVCRT_div(int num
, int denom
)
1889 div_t dt
= div(num
,denom
);
1897 #endif /* ifdef __i386__ */
1900 /*********************************************************************
1903 * [i386] Windows binary compatible - returns the struct in eax/edx.
1906 unsigned __int64 CDECL
MSVCRT_ldiv(MSVCRT_long num
, MSVCRT_long denom
)
1908 ldiv_t ldt
= ldiv(num
,denom
);
1909 return ((unsigned __int64
)ldt
.rem
<< 32) | (MSVCRT_ulong
)ldt
.quot
;
1912 /*********************************************************************
1915 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
1917 MSVCRT_ldiv_t CDECL
MSVCRT_ldiv(MSVCRT_long num
, MSVCRT_long denom
)
1919 ldiv_t result
= ldiv(num
,denom
);
1922 ret
.quot
= result
.quot
;
1923 ret
.rem
= result
.rem
;
1927 #endif /* ifdef __i386__ */
1930 /*********************************************************************
1931 * lldiv (MSVCR100.@)
1933 MSVCRT_lldiv_t
* CDECL
MSVCRT_lldiv(MSVCRT_lldiv_t
*ret
,
1934 MSVCRT_longlong num
, MSVCRT_longlong denom
)
1936 ret
->quot
= num
/ denom
;
1937 ret
->rem
= num
% denom
;
1945 /*********************************************************************
1946 * _adjust_fdiv (MSVCRT.@)
1947 * Used by the MSVC compiler to work around the Pentium FDIV bug.
1949 int MSVCRT__adjust_fdiv
= 0;
1951 /***********************************************************************
1952 * _adj_fdiv_m16i (MSVCRT.@)
1955 * I _think_ this function is intended to work around the Pentium
1958 void __stdcall
_adj_fdiv_m16i( short arg
)
1960 TRACE("(): stub\n");
1963 /***********************************************************************
1964 * _adj_fdiv_m32 (MSVCRT.@)
1967 * I _think_ this function is intended to work around the Pentium
1970 void __stdcall
_adj_fdiv_m32( unsigned int arg
)
1972 TRACE("(): stub\n");
1975 /***********************************************************************
1976 * _adj_fdiv_m32i (MSVCRT.@)
1979 * I _think_ this function is intended to work around the Pentium
1982 void __stdcall
_adj_fdiv_m32i( int arg
)
1984 TRACE("(): stub\n");
1987 /***********************************************************************
1988 * _adj_fdiv_m64 (MSVCRT.@)
1991 * I _think_ this function is intended to work around the Pentium
1994 void __stdcall
_adj_fdiv_m64( unsigned __int64 arg
)
1996 TRACE("(): stub\n");
1999 /***********************************************************************
2000 * _adj_fdiv_r (MSVCRT.@)
2002 * This function is likely to have the wrong number of arguments.
2005 * I _think_ this function is intended to work around the Pentium
2008 void _adj_fdiv_r(void)
2010 TRACE("(): stub\n");
2013 /***********************************************************************
2014 * _adj_fdivr_m16i (MSVCRT.@)
2017 * I _think_ this function is intended to work around the Pentium
2020 void __stdcall
_adj_fdivr_m16i( short arg
)
2022 TRACE("(): stub\n");
2025 /***********************************************************************
2026 * _adj_fdivr_m32 (MSVCRT.@)
2029 * I _think_ this function is intended to work around the Pentium
2032 void __stdcall
_adj_fdivr_m32( unsigned int arg
)
2034 TRACE("(): stub\n");
2037 /***********************************************************************
2038 * _adj_fdivr_m32i (MSVCRT.@)
2041 * I _think_ this function is intended to work around the Pentium
2044 void __stdcall
_adj_fdivr_m32i( int arg
)
2046 TRACE("(): stub\n");
2049 /***********************************************************************
2050 * _adj_fdivr_m64 (MSVCRT.@)
2053 * I _think_ this function is intended to work around the Pentium
2056 void __stdcall
_adj_fdivr_m64( unsigned __int64 arg
)
2058 TRACE("(): stub\n");
2061 /***********************************************************************
2062 * _adj_fpatan (MSVCRT.@)
2064 * This function is likely to have the wrong number of arguments.
2067 * I _think_ this function is intended to work around the Pentium
2070 void _adj_fpatan(void)
2072 TRACE("(): stub\n");
2075 /***********************************************************************
2076 * _adj_fprem (MSVCRT.@)
2078 * This function is likely to have the wrong number of arguments.
2081 * I _think_ this function is intended to work around the Pentium
2084 void _adj_fprem(void)
2086 TRACE("(): stub\n");
2089 /***********************************************************************
2090 * _adj_fprem1 (MSVCRT.@)
2092 * This function is likely to have the wrong number of arguments.
2095 * I _think_ this function is intended to work around the Pentium
2098 void _adj_fprem1(void)
2100 TRACE("(): stub\n");
2103 /***********************************************************************
2104 * _adj_fptan (MSVCRT.@)
2106 * This function is likely to have the wrong number of arguments.
2109 * I _think_ this function is intended to work around the Pentium
2112 void _adj_fptan(void)
2114 TRACE("(): stub\n");
2117 /***********************************************************************
2118 * _safe_fdiv (MSVCRT.@)
2120 * This function is likely to have the wrong number of arguments.
2123 * I _think_ this function is intended to work around the Pentium
2126 void _safe_fdiv(void)
2128 TRACE("(): stub\n");
2131 /***********************************************************************
2132 * _safe_fdivr (MSVCRT.@)
2134 * This function is likely to have the wrong number of arguments.
2137 * I _think_ this function is intended to work around the Pentium
2140 void _safe_fdivr(void)
2142 TRACE("(): stub\n");
2145 /***********************************************************************
2146 * _safe_fprem (MSVCRT.@)
2148 * This function is likely to have the wrong number of arguments.
2151 * I _think_ this function is intended to work around the Pentium
2154 void _safe_fprem(void)
2156 TRACE("(): stub\n");
2159 /***********************************************************************
2160 * _safe_fprem1 (MSVCRT.@)
2163 * This function is likely to have the wrong number of arguments.
2166 * I _think_ this function is intended to work around the Pentium
2169 void _safe_fprem1(void)
2171 TRACE("(): stub\n");
2174 /***********************************************************************
2175 * __libm_sse2_acos (MSVCRT.@)
2177 void __cdecl
MSVCRT___libm_sse2_acos(void)
2180 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2182 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2185 /***********************************************************************
2186 * __libm_sse2_acosf (MSVCRT.@)
2188 void __cdecl
MSVCRT___libm_sse2_acosf(void)
2191 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2193 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2196 /***********************************************************************
2197 * __libm_sse2_asin (MSVCRT.@)
2199 void __cdecl
MSVCRT___libm_sse2_asin(void)
2202 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2204 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2207 /***********************************************************************
2208 * __libm_sse2_asinf (MSVCRT.@)
2210 void __cdecl
MSVCRT___libm_sse2_asinf(void)
2213 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2215 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2218 /***********************************************************************
2219 * __libm_sse2_atan (MSVCRT.@)
2221 void __cdecl
MSVCRT___libm_sse2_atan(void)
2224 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2226 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2229 /***********************************************************************
2230 * __libm_sse2_atan2 (MSVCRT.@)
2232 void __cdecl
MSVCRT___libm_sse2_atan2(void)
2235 __asm__
__volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1
), "=m" (d2
) );
2236 d1
= atan2( d1
, d2
);
2237 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d1
) );
2240 /***********************************************************************
2241 * __libm_sse2_atanf (MSVCRT.@)
2243 void __cdecl
MSVCRT___libm_sse2_atanf(void)
2246 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2248 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2251 /***********************************************************************
2252 * __libm_sse2_cos (MSVCRT.@)
2254 void __cdecl
MSVCRT___libm_sse2_cos(void)
2257 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2259 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2262 /***********************************************************************
2263 * __libm_sse2_cosf (MSVCRT.@)
2265 void __cdecl
MSVCRT___libm_sse2_cosf(void)
2268 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2270 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2273 /***********************************************************************
2274 * __libm_sse2_exp (MSVCRT.@)
2276 void __cdecl
MSVCRT___libm_sse2_exp(void)
2279 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2281 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2284 /***********************************************************************
2285 * __libm_sse2_expf (MSVCRT.@)
2287 void __cdecl
MSVCRT___libm_sse2_expf(void)
2290 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2292 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2295 /***********************************************************************
2296 * __libm_sse2_log (MSVCRT.@)
2298 void __cdecl
MSVCRT___libm_sse2_log(void)
2301 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2303 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2306 /***********************************************************************
2307 * __libm_sse2_log10 (MSVCRT.@)
2309 void __cdecl
MSVCRT___libm_sse2_log10(void)
2312 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2314 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2317 /***********************************************************************
2318 * __libm_sse2_log10f (MSVCRT.@)
2320 void __cdecl
MSVCRT___libm_sse2_log10f(void)
2323 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2325 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2328 /***********************************************************************
2329 * __libm_sse2_logf (MSVCRT.@)
2331 void __cdecl
MSVCRT___libm_sse2_logf(void)
2334 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2336 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2339 /***********************************************************************
2340 * __libm_sse2_pow (MSVCRT.@)
2342 void __cdecl
MSVCRT___libm_sse2_pow(void)
2345 __asm__
__volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1
), "=m" (d2
) );
2347 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d1
) );
2350 /***********************************************************************
2351 * __libm_sse2_powf (MSVCRT.@)
2353 void __cdecl
MSVCRT___libm_sse2_powf(void)
2356 __asm__
__volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1
), "=g" (f2
) );
2357 f1
= powf( f1
, f2
);
2358 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f1
) );
2361 /***********************************************************************
2362 * __libm_sse2_sin (MSVCRT.@)
2364 void __cdecl
MSVCRT___libm_sse2_sin(void)
2367 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2369 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2372 /***********************************************************************
2373 * __libm_sse2_sinf (MSVCRT.@)
2375 void __cdecl
MSVCRT___libm_sse2_sinf(void)
2378 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2380 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2383 /***********************************************************************
2384 * __libm_sse2_tan (MSVCRT.@)
2386 void __cdecl
MSVCRT___libm_sse2_tan(void)
2389 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2391 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2394 /***********************************************************************
2395 * __libm_sse2_tanf (MSVCRT.@)
2397 void __cdecl
MSVCRT___libm_sse2_tanf(void)
2400 __asm__
__volatile__( "movd %%xmm0,%0" : "=g" (f
) );
2402 __asm__
__volatile__( "movd %0,%%xmm0" : : "g" (f
) );
2405 /***********************************************************************
2406 * __libm_sse2_sqrt_precise (MSVCR110.@)
2408 void __cdecl
MSVCRT___libm_sse2_sqrt_precise(void)
2411 __asm__
__volatile__( "movq %%xmm0,%0" : "=m" (d
) );
2413 __asm__
__volatile__( "movq %0,%%xmm0" : : "m" (d
) );
2416 #endif /* __i386__ */
2418 /*********************************************************************
2421 double CDECL
MSVCR120_cbrt(double x
)
2426 return x
< 0 ? -pow(-x
, 1.0 / 3.0) : pow(x
, 1.0 / 3.0);
2430 /*********************************************************************
2431 * cbrtf (MSVCR120.@)
2433 float CDECL
MSVCR120_cbrtf(float x
)
2438 return MSVCR120_cbrt(x
);
2442 /*********************************************************************
2443 * cbrtl (MSVCR120.@)
2445 LDOUBLE CDECL
MSVCR120_cbrtl(LDOUBLE x
)
2447 return MSVCR120_cbrt(x
);
2450 /*********************************************************************
2453 double CDECL
MSVCR120_exp2(double x
)
2456 double ret
= exp2(x
);
2458 double ret
= pow(2, x
);
2460 if (isfinite(x
) && !isfinite(ret
)) *MSVCRT__errno() = MSVCRT_ERANGE
;
2464 /*********************************************************************
2465 * exp2f (MSVCR120.@)
2467 float CDECL
MSVCR120_exp2f(float x
)
2470 float ret
= exp2f(x
);
2471 if (finitef(x
) && !finitef(ret
)) *MSVCRT__errno() = MSVCRT_ERANGE
;
2474 return MSVCR120_exp2(x
);
2478 /*********************************************************************
2479 * exp2l (MSVCR120.@)
2481 LDOUBLE CDECL
MSVCR120_exp2l(LDOUBLE x
)
2483 return MSVCR120_exp2(x
);
2486 /*********************************************************************
2487 * expm1 (MSVCR120.@)
2489 double CDECL
MSVCR120_expm1(double x
)
2492 double ret
= expm1(x
);
2494 double ret
= exp(x
) - 1;
2496 if (isfinite(x
) && !isfinite(ret
)) *MSVCRT__errno() = MSVCRT_ERANGE
;
2500 /*********************************************************************
2501 * expm1f (MSVCR120.@)
2503 float CDECL
MSVCR120_expm1f(float x
)
2506 float ret
= expm1f(x
);
2508 float ret
= exp(x
) - 1;
2510 if (finitef(x
) && !finitef(ret
)) *MSVCRT__errno() = MSVCRT_ERANGE
;
2514 /*********************************************************************
2515 * expm1l (MSVCR120.@)
2517 LDOUBLE CDECL
MSVCR120_expm1l(LDOUBLE x
)
2519 return MSVCR120_expm1(x
);
2522 /*********************************************************************
2523 * log1p (MSVCR120.@)
2525 double CDECL
MSVCR120_log1p(double x
)
2527 if (x
< -1) *MSVCRT__errno() = MSVCRT_EDOM
;
2528 else if (x
== -1) *MSVCRT__errno() = MSVCRT_ERANGE
;
2536 /*********************************************************************
2537 * log1pf (MSVCR120.@)
2539 float CDECL
MSVCR120_log1pf(float x
)
2541 if (x
< -1) *MSVCRT__errno() = MSVCRT_EDOM
;
2542 else if (x
== -1) *MSVCRT__errno() = MSVCRT_ERANGE
;
2550 /*********************************************************************
2551 * log1pl (MSVCR120.@)
2553 LDOUBLE CDECL
MSVCR120_log1pl(LDOUBLE x
)
2555 return MSVCR120_log1p(x
);
2558 /*********************************************************************
2561 double CDECL
MSVCR120_log2(double x
)
2563 if (x
< 0) *MSVCRT__errno() = MSVCRT_EDOM
;
2564 else if (x
== 0) *MSVCRT__errno() = MSVCRT_ERANGE
;
2568 return log(x
) / log(2);
2572 /*********************************************************************
2573 * log2f (MSVCR120.@)
2575 float CDECL
MSVCR120_log2f(float x
)
2578 if (x
< 0) *MSVCRT__errno() = MSVCRT_EDOM
;
2579 else if (x
== 0) *MSVCRT__errno() = MSVCRT_ERANGE
;
2582 return MSVCR120_log2(x
);
2586 /*********************************************************************
2587 * log2l (MSVCR120.@)
2589 LDOUBLE CDECL
MSVCR120_log2l(LDOUBLE x
)
2591 return MSVCR120_log2(x
);
2594 /*********************************************************************
2597 double CDECL
MSVCR120_rint(double x
)
2602 /*********************************************************************
2603 * rintf (MSVCR120.@)
2605 float CDECL
MSVCR120_rintf(float x
)
2610 /*********************************************************************
2611 * rintl (MSVCR120.@)
2613 LDOUBLE CDECL
MSVCR120_rintl(LDOUBLE x
)
2615 return MSVCR120_rint(x
);
2618 /*********************************************************************
2619 * lrint (MSVCR120.@)
2621 MSVCRT_long CDECL
MSVCR120_lrint(double x
)
2626 /*********************************************************************
2627 * lrintf (MSVCR120.@)
2629 MSVCRT_long CDECL
MSVCR120_lrintf(float x
)
2634 /*********************************************************************
2635 * lrintl (MSVCR120.@)
2637 MSVCRT_long CDECL
MSVCR120_lrintl(LDOUBLE x
)
2639 return MSVCR120_lrint(x
);
2642 /*********************************************************************
2643 * llrint (MSVCR120.@)
2645 MSVCRT_longlong CDECL
MSVCR120_llrint(double x
)
2650 /*********************************************************************
2651 * llrintf (MSVCR120.@)
2653 MSVCRT_longlong CDECL
MSVCR120_llrintf(float x
)
2658 /*********************************************************************
2659 * rintl (MSVCR120.@)
2661 MSVCRT_longlong CDECL
MSVCR120_llrintl(LDOUBLE x
)
2663 return MSVCR120_llrint(x
);
2668 /*********************************************************************
2669 * round (MSVCR120.@)
2671 double CDECL
MSVCR120_round(double x
)
2676 return MSVCR120_rint(x
);
2680 /*********************************************************************
2681 * roundf (MSVCR120.@)
2683 float CDECL
MSVCR120_roundf(float x
)
2688 return MSVCR120_round(x
);
2692 /*********************************************************************
2693 * roundl (MSVCR120.@)
2695 LDOUBLE CDECL
MSVCR120_roundl(LDOUBLE x
)
2697 return MSVCR120_round(x
);
2700 /*********************************************************************
2701 * lround (MSVCR120.@)
2703 MSVCRT_long CDECL
MSVCR120_lround(double x
)
2708 return MSVCR120_round(x
);
2712 /*********************************************************************
2713 * lroundf (MSVCR120.@)
2715 MSVCRT_long CDECL
MSVCR120_lroundf(float x
)
2720 return MSVCR120_lround(x
);
2724 /*********************************************************************
2725 * lroundl (MSVCR120.@)
2727 MSVCRT_long CDECL
MSVCR120_lroundl(LDOUBLE x
)
2729 return MSVCR120_lround(x
);
2732 /*********************************************************************
2733 * llround (MSVCR120.@)
2735 MSVCRT_longlong CDECL
MSVCR120_llround(double x
)
2740 return MSVCR120_round(x
);
2744 /*********************************************************************
2745 * llroundf (MSVCR120.@)
2747 MSVCRT_longlong CDECL
MSVCR120_llroundf(float x
)
2749 #ifdef HAVE_LLROUNDF
2752 return MSVCR120_llround(x
);
2756 /*********************************************************************
2757 * roundl (MSVCR120.@)
2759 MSVCRT_longlong CDECL
MSVCR120_llroundl(LDOUBLE x
)
2761 return MSVCR120_llround(x
);
2764 /*********************************************************************
2765 * trunc (MSVCR120.@)
2767 double CDECL
MSVCR120_trunc(double x
)
2772 return (x
> 0) ? floor(x
) : ceil(x
);
2776 /*********************************************************************
2777 * truncf (MSVCR120.@)
2779 float CDECL
MSVCR120_truncf(float x
)
2784 return MSVCR120_trunc(x
);
2788 /*********************************************************************
2789 * truncl (MSVCR120.@)
2791 LDOUBLE CDECL
MSVCR120_truncl(LDOUBLE x
)
2793 return MSVCR120_trunc(x
);
2796 /*********************************************************************
2797 * _dclass (MSVCR120.@)
2799 short CDECL
MSVCR120__dclass(double x
)
2801 switch (MSVCRT__fpclass(x
)) {
2802 case MSVCRT__FPCLASS_QNAN
:
2803 case MSVCRT__FPCLASS_SNAN
:
2804 return MSVCRT_FP_NAN
;
2805 case MSVCRT__FPCLASS_NINF
:
2806 case MSVCRT__FPCLASS_PINF
:
2807 return MSVCRT_FP_INFINITE
;
2808 case MSVCRT__FPCLASS_ND
:
2809 case MSVCRT__FPCLASS_PD
:
2810 return MSVCRT_FP_SUBNORMAL
;
2811 case MSVCRT__FPCLASS_NN
:
2812 case MSVCRT__FPCLASS_PN
:
2814 return MSVCRT_FP_NORMAL
;
2815 case MSVCRT__FPCLASS_NZ
:
2816 case MSVCRT__FPCLASS_PZ
:
2817 return MSVCRT_FP_ZERO
;
2821 /*********************************************************************
2822 * _fdclass (MSVCR120.@)
2824 short CDECL
MSVCR120__fdclass(float x
)
2826 return MSVCR120__dclass(x
);
2829 /*********************************************************************
2830 * _ldclass (MSVCR120.@)
2832 short CDECL
MSVCR120__ldclass(LDOUBLE x
)
2834 return MSVCR120__dclass(x
);
2837 /*********************************************************************
2838 * _dtest (MSVCR120.@)
2840 short CDECL
MSVCR120__dtest(double *x
)
2842 return MSVCR120__dclass(*x
);
2845 /*********************************************************************
2846 * _fdtest (MSVCR120.@)
2848 short CDECL
MSVCR120__fdtest(float *x
)
2850 return MSVCR120__dclass(*x
);
2853 /*********************************************************************
2854 * _ldtest (MSVCR120.@)
2856 short CDECL
MSVCR120__ldtest(LDOUBLE
*x
)
2858 return MSVCR120__dclass(*x
);
2861 /*********************************************************************
2864 double CDECL
MSVCR120_erf(double x
)
2869 /* Abramowitz and Stegun approximation, maximum error: 1.5*10^-7 */
2871 int sign
= signbit(x
);
2874 t
= 1 / (1 + 0.3275911 * x
);
2875 y
= ((((1.061405429*t
- 1.453152027)*t
+ 1.421413741)*t
- 0.284496736)*t
+ 0.254829592)*t
;
2876 y
= 1.0 - y
*exp(-x
*x
);
2877 return sign
? -y
: y
;
2881 /*********************************************************************
2884 float CDECL
MSVCR120_erff(float x
)
2889 return MSVCR120_erf(x
);
2893 /*********************************************************************
2896 LDOUBLE CDECL
MSVCR120_erfl(LDOUBLE x
)
2898 return MSVCR120_erf(x
);
2901 /*********************************************************************
2904 double CDECL
MSVCR120_erfc(double x
)
2909 return 1 - MSVCR120_erf(x
);
2913 /*********************************************************************
2914 * erfcf (MSVCR120.@)
2916 float CDECL
MSVCR120_erfcf(float x
)
2921 return MSVCR120_erfc(x
);
2925 /*********************************************************************
2926 * erfcl (MSVCR120.@)
2928 LDOUBLE CDECL
MSVCR120_erfcl(LDOUBLE x
)
2930 return MSVCR120_erfc(x
);
2933 /*********************************************************************
2934 * fmaxf (MSVCR120.@)
2936 float CDECL
MSVCR120_fmaxf(float x
, float y
)
2943 return signbit(x
) ? y
: x
;
2947 /*********************************************************************
2950 double CDECL
MSVCR120_fmax(double x
, double y
)
2957 return signbit(x
) ? y
: x
;
2961 /*********************************************************************
2962 * _fdsign (MSVCR120.@)
2964 int CDECL
MSVCR120__fdsign(float x
)
2966 return signbit(x
) ? 0x8000 : 0;
2969 /*********************************************************************
2970 * _dsign (MSVCR120.@)
2972 int CDECL
MSVCR120__dsign(double x
)
2974 return signbit(x
) ? 0x8000 : 0;
2978 /*********************************************************************
2979 * _dpcomp (MSVCR120.@)
2981 int CDECL
MSVCR120__dpcomp(double x
, double y
)
2983 if(isnan(x
) || isnan(y
))
2986 if(x
== y
) return 2;
2987 return x
< y
? 1 : 4;
2990 /*********************************************************************
2991 * _fdpcomp (MSVCR120.@)
2993 int CDECL
MSVCR120__fdpcomp(float x
, float y
)
2995 return MSVCR120__dpcomp(x
, y
);
2998 /*********************************************************************
2999 * fminf (MSVCR120.@)
3001 float CDECL
MSVCR120_fminf(float x
, float y
)
3008 return signbit(x
) ? x
: y
;
3012 /*********************************************************************
3015 double CDECL
MSVCR120_fmin(double x
, double y
)
3022 return signbit(x
) ? x
: y
;
3026 /*********************************************************************
3027 * asinh (MSVCR120.@)
3029 double CDECL
MSVCR120_asinh(double x
)
3034 if (!isfinite(x
*x
+1)) return log(2) + log(x
);
3035 return log(x
+ sqrt(x
*x
+1));
3039 /*********************************************************************
3040 * asinhf (MSVCR120.@)
3042 float CDECL
MSVCR120_asinhf(float x
)
3047 return MSVCR120_asinh(x
);
3051 /*********************************************************************
3052 * asinhl (MSVCR120.@)
3054 LDOUBLE CDECL
MSVCR120_asinhl(LDOUBLE x
)
3056 return MSVCR120_asinh(x
);
3059 /*********************************************************************
3060 * acosh (MSVCR120.@)
3062 double CDECL
MSVCR120_acosh(double x
)
3064 if (x
< 1) *MSVCRT__errno() = MSVCRT_EDOM
;
3072 MSVCRT_fegetenv(&env
);
3073 env
.status
|= MSVCRT__SW_INVALID
;
3074 MSVCRT_fesetenv(&env
);
3077 if (!isfinite(x
*x
)) return log(2) + log(x
);
3078 return log(x
+ sqrt(x
*x
-1));
3082 /*********************************************************************
3083 * acoshf (MSVCR120.@)
3085 float CDECL
MSVCR120_acoshf(float x
)
3088 if (x
< 1) *MSVCRT__errno() = MSVCRT_EDOM
;
3092 return MSVCR120_acosh(x
);
3096 /*********************************************************************
3097 * acoshl (MSVCR120.@)
3099 LDOUBLE CDECL
MSVCR120_acoshl(LDOUBLE x
)
3101 return MSVCR120_acosh(x
);
3104 /*********************************************************************
3105 * atanh (MSVCR120.@)
3107 double CDECL
MSVCR120_atanh(double x
)
3111 if (x
> 1 || x
< -1) {
3114 *MSVCRT__errno() = MSVCRT_EDOM
;
3116 /* on Linux atanh returns -NAN in this case */
3117 MSVCRT_fegetenv(&env
);
3118 env
.status
|= MSVCRT__SW_INVALID
;
3119 MSVCRT_fesetenv(&env
);
3126 if (-1e-6 < x
&& x
< 1e-6) ret
= x
+ x
*x
*x
/3;
3127 else ret
= (log(1+x
) - log(1-x
)) / 2;
3130 if (!isfinite(ret
)) *MSVCRT__errno() = MSVCRT_ERANGE
;
3134 /*********************************************************************
3135 * atanhf (MSVCR120.@)
3137 float CDECL
MSVCR120_atanhf(float x
)
3142 if (x
> 1 || x
< -1) {
3145 *MSVCRT__errno() = MSVCRT_EDOM
;
3147 MSVCRT_fegetenv(&env
);
3148 env
.status
|= MSVCRT__SW_INVALID
;
3149 MSVCRT_fesetenv(&env
);
3155 if (!finitef(ret
)) *MSVCRT__errno() = MSVCRT_ERANGE
;
3158 return MSVCR120_atanh(x
);
3162 /*********************************************************************
3163 * atanhl (MSVCR120.@)
3165 LDOUBLE CDECL
MSVCR120_atanhl(LDOUBLE x
)
3167 return MSVCR120_atanh(x
);
3170 #endif /* _MSVCR_VER>=120 */
3172 /*********************************************************************
3174 * scalbn (MSVCR120.@)
3175 * scalbln (MSVCR120.@)
3177 double CDECL
MSVCRT__scalb(double num
, MSVCRT_long power
)
3179 return MSVCRT_ldexp(num
, power
);
3182 /*********************************************************************
3183 * _scalbf (MSVCRT.@)
3184 * scalbnf (MSVCR120.@)
3185 * scalblnf (MSVCR120.@)
3187 float CDECL
MSVCRT__scalbf(float num
, MSVCRT_long power
)
3189 return MSVCRT_ldexp(num
, power
);
3194 /*********************************************************************
3195 * scalbnl (MSVCR120.@)
3196 * scalblnl (MSVCR120.@)
3198 LDOUBLE CDECL
MSVCR120_scalbnl(LDOUBLE num
, MSVCRT_long power
)
3200 return MSVCRT__scalb(num
, power
);
3203 /*********************************************************************
3204 * remainder (MSVCR120.@)
3206 double CDECL
MSVCR120_remainder(double x
, double y
)
3208 #ifdef HAVE_REMAINDER
3209 /* this matches 64-bit Windows. 32-bit Windows is slightly different */
3210 if(!finite(x
)) *MSVCRT__errno() = MSVCRT_EDOM
;
3211 if(isnan(y
) || y
==0.0) *MSVCRT__errno() = MSVCRT_EDOM
;
3212 return remainder(x
, y
);
3214 FIXME( "not implemented\n" );
3219 /*********************************************************************
3220 * remainderf (MSVCR120.@)
3222 float CDECL
MSVCR120_remainderf(float x
, float y
)
3224 #ifdef HAVE_REMAINDERF
3225 /* this matches 64-bit Windows. 32-bit Windows is slightly different */
3226 if(!finitef(x
)) *MSVCRT__errno() = MSVCRT_EDOM
;
3227 if(isnan(y
) || y
==0.0f
) *MSVCRT__errno() = MSVCRT_EDOM
;
3228 return remainderf(x
, y
);
3230 FIXME( "not implemented\n" );
3235 /*********************************************************************
3236 * remainderl (MSVCR120.@)
3238 LDOUBLE CDECL
MSVCR120_remainderl(LDOUBLE x
, LDOUBLE y
)
3240 return MSVCR120_remainder(x
, y
);
3243 /*********************************************************************
3244 * lgamma (MSVCR120.@)
3246 double CDECL
MSVCR120_lgamma(double x
)
3251 FIXME( "not implemented\n" );
3256 /*********************************************************************
3257 * lgammaf (MSVCR120.@)
3259 float CDECL
MSVCR120_lgammaf(float x
)
3264 FIXME( "not implemented\n" );
3269 /*********************************************************************
3270 * lgammal (MSVCR120.@)
3272 LDOUBLE CDECL
MSVCR120_lgammal(LDOUBLE x
)
3274 return MSVCR120_lgamma(x
);
3277 /*********************************************************************
3280 double CDECL
MSVCR120_nan(const char *tagp
)
3282 /* Windows ignores input (MSDN) */
3286 /*********************************************************************
3289 float CDECL
MSVCR120_nanf(const char *tagp
)
3294 /*********************************************************************
3295 * _except1 (MSVCR120.@)
3297 * - find meaning of ignored cw and operation bits
3300 double CDECL
_except1(DWORD fpe
, _FP_OPERATION_CODE op
, double arg
, double res
, DWORD cw
, void *unk
)
3302 ULONG_PTR exception_arg
;
3303 DWORD exception
= 0;
3308 TRACE("(%x %x %lf %lf %x %p)\n", fpe
, op
, arg
, res
, cw
, unk
);
3311 cw
= ((cw
>> 7) & 0x3f) | ((cw
>> 3) & 0xc00);
3313 operation
= op
<< 5;
3314 exception_arg
= (ULONG_PTR
)&operation
;
3316 MSVCRT_fegetenv(&env
);
3318 if (fpe
& 0x1) { /* overflow */
3319 if ((fpe
== 0x1 && (cw
& 0x8)) || (fpe
==0x11 && (cw
& 0x28))) {
3320 /* 32-bit version also sets SW_INEXACT here */
3321 env
.status
|= MSVCRT__SW_OVERFLOW
;
3322 if (fpe
& 0x10) env
.status
|= MSVCRT__SW_INEXACT
;
3323 res
= signbit(res
) ? -INFINITY
: INFINITY
;
3325 exception
= EXCEPTION_FLT_OVERFLOW
;
3327 } else if (fpe
& 0x2) { /* underflow */
3328 if ((fpe
== 0x2 && (cw
& 0x10)) || (fpe
==0x12 && (cw
& 0x30))) {
3329 env
.status
|= MSVCRT__SW_UNDERFLOW
;
3330 if (fpe
& 0x10) env
.status
|= MSVCRT__SW_INEXACT
;
3331 res
= signbit(res
) ? -0.0 : 0.0;
3333 exception
= EXCEPTION_FLT_UNDERFLOW
;
3335 } else if (fpe
& 0x4) { /* zerodivide */
3336 if ((fpe
== 0x4 && (cw
& 0x4)) || (fpe
==0x14 && (cw
& 0x24))) {
3337 env
.status
|= MSVCRT__SW_ZERODIVIDE
;
3338 if (fpe
& 0x10) env
.status
|= MSVCRT__SW_INEXACT
;
3340 exception
= EXCEPTION_FLT_DIVIDE_BY_ZERO
;
3342 } else if (fpe
& 0x8) { /* invalid */
3343 if (fpe
== 0x8 && (cw
& 0x1)) {
3344 env
.status
|= MSVCRT__SW_INVALID
;
3346 exception
= EXCEPTION_FLT_INVALID_OPERATION
;
3348 } else if (fpe
& 0x10) { /* inexact */
3349 if (fpe
== 0x10 && (cw
& 0x20)) {
3350 env
.status
|= MSVCRT__SW_INEXACT
;
3352 exception
= EXCEPTION_FLT_INEXACT_RESULT
;
3358 MSVCRT_fesetenv(&env
);
3360 RaiseException(exception
, 0, 1, &exception_arg
);
3362 if (cw
& 0x1) fpword
|= MSVCRT__EM_INVALID
;
3363 if (cw
& 0x2) fpword
|= MSVCRT__EM_DENORMAL
;
3364 if (cw
& 0x4) fpword
|= MSVCRT__EM_ZERODIVIDE
;
3365 if (cw
& 0x8) fpword
|= MSVCRT__EM_OVERFLOW
;
3366 if (cw
& 0x10) fpword
|= MSVCRT__EM_UNDERFLOW
;
3367 if (cw
& 0x20) fpword
|= MSVCRT__EM_INEXACT
;
3370 case 0xc00: fpword
|= MSVCRT__RC_UP
|MSVCRT__RC_DOWN
; break;
3371 case 0x800: fpword
|= MSVCRT__RC_UP
; break;
3372 case 0x400: fpword
|= MSVCRT__RC_DOWN
; break;
3376 case 0x0: fpword
|= MSVCRT__PC_24
; break;
3377 case 0x200: fpword
|= MSVCRT__PC_53
; break;
3378 case 0x300: fpword
|= MSVCRT__PC_64
; break;
3380 if (cw
& 0x1000) fpword
|= MSVCRT__IC_AFFINE
;
3381 _control87(fpword
, 0xffffffff);
3386 _Dcomplex
* CDECL
MSVCR120__Cbuild(_Dcomplex
*ret
, double r
, double i
)
3393 double CDECL
MSVCR120_creal(_Dcomplex z
)
3398 #endif /* _MSVCR_VER>=120 */