ReactOS 0.4.17-dev-1321-g5c122a9
math.c
Go to the documentation of this file.
1/*
2 * msvcrt.dll math functions
3 *
4 * Copyright 2000 Jon Griffiths
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 *
20 *
21 * For functions copied from musl libc (http://musl.libc.org/):
22 * ====================================================
23 * Copyright 2005-2020 Rich Felker, et al.
24 *
25 * Permission is hereby granted, free of charge, to any person obtaining
26 * a copy of this software and associated documentation files (the
27 * "Software"), to deal in the Software without restriction, including
28 * without limitation the rights to use, copy, modify, merge, publish,
29 * distribute, sublicense, and/or sell copies of the Software, and to
30 * permit persons to whom the Software is furnished to do so, subject to
31 * the following conditions:
32 *
33 * The above copyright notice and this permission notice shall be
34 * included in all copies or substantial portions of the Software.
35 * ====================================================
36 */
37
38#include <assert.h>
39#include <complex.h>
40#include <stdio.h>
41#include <fenv.h>
42#include <fpieee.h>
43#include <limits.h>
44#include <locale.h>
45#include <math.h>
46
47#include "msvcrt.h"
48#include "winternl.h"
49
50#include "wine/asm.h"
51#include "wine/debug.h"
52
54
55#ifdef _MSC_VER
56#pragma function(abs,labs,div,ldiv)
57#endif
58
59#undef div
60#undef ldiv
61
62#define _DOMAIN 1 /* domain error in argument */
63#define _SING 2 /* singularity */
64#define _OVERFLOW 3 /* range overflow */
65#define _UNDERFLOW 4 /* range underflow */
66
68
70
73
75{
77#if _MSVCR_VER <=71
79#else
81#endif
82}
83
84static inline double ret_nan( BOOL update_sw )
85{
86 double x = 1.0;
87 if (!update_sw) return -NAN;
88 return (x - x) / (x - x);
89}
90
91#define SET_X87_CW(MASK) \
92 "subl $4, %esp\n\t" \
93 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
94 "fnstcw (%esp)\n\t" \
95 "movw (%esp), %ax\n\t" \
96 "movw %ax, 2(%esp)\n\t" \
97 "testw $" #MASK ", %ax\n\t" \
98 "jz 1f\n\t" \
99 "andw $~" #MASK ", %ax\n\t" \
100 "movw %ax, 2(%esp)\n\t" \
101 "fldcw 2(%esp)\n\t" \
102 "1:\n\t"
103
104#define RESET_X87_CW \
105 "movw (%esp), %ax\n\t" \
106 "cmpw %ax, 2(%esp)\n\t" \
107 "je 1f\n\t" \
108 "fstpl 8(%esp)\n\t" \
109 "fldcw (%esp)\n\t" \
110 "fldl 8(%esp)\n\t" \
111 "fwait\n\t" \
112 "1:\n\t" \
113 "addl $4, %esp\n\t" \
114 __ASM_CFI(".cfi_adjust_cfa_offset -4\n\t")
115
116/*********************************************************************
117 * _matherr (CRTDLL.@)
118 */
120{
121 return 0;
122}
123
124
125double math_error(int type, const char *name, double arg1, double arg2, double retval)
126{
127 struct _exception exception = {type, (char *)name, arg1, arg2, retval};
128
129 TRACE("(%d, %s, %g, %g, %g)\n", type, debugstr_a(name), arg1, arg2, retval);
130
132 return exception.retval;
133
134 switch (type)
135 {
136 case 0:
137 /* don't set errno */
138 break;
139 case _DOMAIN:
140 *_errno() = EDOM;
141 break;
142 case _SING:
143 case _OVERFLOW:
144 *_errno() = ERANGE;
145 break;
146 case _UNDERFLOW:
147 /* don't set errno */
148 break;
149 default:
150 ERR("Unhandled math error!\n");
151 }
152
153 return exception.retval;
154}
155
156/*********************************************************************
157 * __setusermatherr (MSVCRT.@)
158 */
160{
162 TRACE("new matherr handler %p\n", func);
163}
164
165/*********************************************************************
166 * _set_SSE2_enable (MSVCRT.@)
167 */
169{
171 return sse2_enabled;
172}
173
174#if defined(_WIN64)
175# if _MSVCR_VER>=140
176/*********************************************************************
177 * _get_FMA3_enable (UCRTBASE.@)
178 */
179int CDECL _get_FMA3_enable(void)
180{
181 FIXME("() stub\n");
182 return 0;
183}
184# endif
185
186# if _MSVCR_VER>=120
187/*********************************************************************
188 * _set_FMA3_enable (MSVCR120.@)
189 */
191{
192 FIXME("(%x) stub\n", flag);
193 return 0;
194}
195# endif
196#endif
197
198#if !defined(__i386__) || _MSVCR_VER>=120
199
200/*********************************************************************
201 * _chgsignf (MSVCRT.@)
202 */
203float CDECL _chgsignf( float num )
204{
205 union { float f; UINT32 i; } u = { num };
206 u.i ^= 0x80000000;
207 return u.f;
208}
209
210#endif
211
212#ifndef __i386__
213
214/*********************************************************************
215 * _fpclassf (MSVCRT.@)
216 */
217int CDECL _fpclassf( float num )
218{
219 union { float f; UINT32 i; } u = { num };
220 int e = u.i >> 23 & 0xff;
221 int s = u.i >> 31;
222
223 switch (e)
224 {
225 case 0:
226 if (u.i << 1) return s ? _FPCLASS_ND : _FPCLASS_PD;
227 return s ? _FPCLASS_NZ : _FPCLASS_PZ;
228 case 0xff:
229 if (u.i << 9) return ((u.i >> 22) & 1) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
230 return s ? _FPCLASS_NINF : _FPCLASS_PINF;
231 default:
232 return s ? _FPCLASS_NN : _FPCLASS_PN;
233 }
234}
235
236/*********************************************************************
237 * _finitef (MSVCRT.@)
238 */
239int CDECL _finitef( float num )
240{
241 union { float f; UINT32 i; } u = { num };
242 return (u.i & 0x7fffffff) < 0x7f800000;
243}
244
245/*********************************************************************
246 * _isnanf (MSVCRT.@)
247 */
248int CDECL _isnanf( float num )
249{
250 union { float f; UINT32 i; } u = { num };
251 return (u.i & 0x7fffffff) > 0x7f800000;
252}
253
254/*********************************************************************
255 * atanf (MSVCRT.@)
256 */
257#if _MSVCR_VER == 0 /* other versions call atanf() directly */
258float CDECL MSVCRT_atanf( float x )
259{
260 if (isnan(x)) return math_error(_DOMAIN, "atanf", x, 0, x);
261 return atanf( x );
262}
263#endif
264
265#ifndef __i386__
266extern short CDECL _fdclass(float x);
267
268static BOOL sqrtf_validate( float *x )
269{
270 short c = _fdclass(*x);
271
272 if (c == FP_ZERO) return FALSE;
273 if (c == FP_NAN) return FALSE;
274 if (signbit(*x))
275 {
276 *x = math_error(_DOMAIN, "sqrtf", *x, 0, ret_nan(TRUE));
277 return FALSE;
278 }
279 if (c == FP_INFINITE) return FALSE;
280 return TRUE;
281}
282
283#ifdef __arm64ec__
284static float __attribute__((naked)) CDECL asm_sqrtf(float x)
285{
286 asm( "fsqrt s0,s0; ret" );
287}
288#elif defined __aarch64__
289float CDECL asm_sqrtf(float);
290__ASM_GLOBAL_FUNC( asm_sqrtf, "fsqrt s0,s0; ret" )
291#elif defined __arm__
292float CDECL asm_sqrtf(float);
293__ASM_GLOBAL_FUNC( asm_sqrtf, "vsqrt s0,s0; bx lr" )
294#elif defined __x86_64__
295float CDECL asm_sqrtf(float);
296__ASM_GLOBAL_FUNC( asm_sqrtf, "sqrtss %xmm0, %xmm0; ret" )
297#endif
298#endif
299
300/*********************************************************************
301 * sqrtf (MSVCRT.@)
302 */
303float CDECL MSVCRT_sqrtf( float x )
304{
305#ifndef __i386__
306 if (!sqrtf_validate(&x))
307 return x;
308
309 return asm_sqrtf(x);
310#else
311 return sqrtf( x );
312#endif
313}
314
315/*********************************************************************
316 * tanhf (MSVCRT.@)
317 */
318#if _MSVCR_VER < 140 /* other versions call tanhf() directly */
319float CDECL MSVCRT_tanhf( float x )
320{
321 if (isnan( x ))
322 {
323 *(UINT32*)&x |= 0x400000;
324 return math_error(_DOMAIN, "tanhf", x, 0, x);
325 }
326 return tanhf( x );
327}
328#endif
329
330#endif
331
332/*********************************************************************
333 * asin (MSVCRT.@)
334 */
335#ifdef __i386__
336double CDECL x87_asin(double);
337__ASM_GLOBAL_FUNC( x87_asin,
338 "fldl 4(%esp)\n\t"
339 SET_X87_CW(~0x37f)
340 "fld %st\n\t"
341 "fld1\n\t"
342 "fsubp\n\t"
343 "fld1\n\t"
344 "fadd %st(2)\n\t"
345 "fmulp\n\t"
346 "fsqrt\n\t"
347 "fpatan\n\t"
349 "ret" )
350#endif
351
352double CDECL MSVCRT_asin( double x )
353{
354#ifdef __i386__
355 unsigned int x87_cw, sse2_cw;
356 unsigned int hx = *(ULONGLONG*)&x >> 32;
357 unsigned int ix = hx & 0x7fffffff;
358
359 if (isnan(x)) return math_error(_DOMAIN, "asin", x, 0, x);
360
361 /* |x| < 1 */
362 if (ix < 0x3ff00000)
363 {
364 __control87_2(0, 0, &x87_cw, &sse2_cw);
365 if (!sse2_enabled || (x87_cw & _MCW_EM) != _MCW_EM
366 || (sse2_cw & (_MCW_EM | _MCW_RC)) != _MCW_EM)
367 return x87_asin(x);
368 }
369#else
370 if (isnan(x)) return x;
371#endif
372
373 return asin( x );
374}
375
376/*********************************************************************
377 * atan (MSVCRT.@)
378 */
379#if _MSVCR_VER == 0 /* other versions call atan() directly */
380double CDECL MSVCRT_atan( double x )
381{
382 if (isnan(x)) return math_error(_DOMAIN, "atan", x, 0, x);
383 return atan( x );
384}
385#endif
386
387/*********************************************************************
388 * exp (MSVCRT.@)
389 */
390#if _MSVCR_VER == 0 /* other versions call exp() directly */
391double CDECL MSVCRT_exp( double x )
392{
393 if (isnan( x )) return math_error(_DOMAIN, "exp", x, 0, 1.0 + x);
394 return exp( x );
395}
396#endif
397
398extern short CDECL _dclass(double x);
399
400static BOOL sqrt_validate( double *x, BOOL update_sw )
401{
402 short c = _dclass(*x);
403
404 if (c == FP_ZERO) return FALSE;
405 if (c == FP_NAN)
406 {
407#ifdef __i386__
408 if (update_sw)
409 *x = math_error(_DOMAIN, "sqrt", *x, 0, *x);
410#else
411 /* set signaling bit */
412 *(ULONGLONG*)x |= 0x8000000000000ULL;
413#endif
414 return FALSE;
415 }
416 if (signbit(*x))
417 {
418 *x = math_error(_DOMAIN, "sqrt", *x, 0, ret_nan(update_sw));
419 return FALSE;
420 }
421 if (c == FP_INFINITE) return FALSE;
422 return TRUE;
423}
424
425#ifdef __arm64ec__
426static double __attribute__((naked)) CDECL asm_sqrt(double x)
427{
428 asm( "fsqrt d0,d0; ret" );
429}
430#elif defined __aarch64__
431double CDECL asm_sqrt(double);
432__ASM_GLOBAL_FUNC( asm_sqrt, "fsqrt d0,d0; ret" )
433#elif defined __arm__
434double CDECL asm_sqrt(double);
435__ASM_GLOBAL_FUNC( asm_sqrt, "vsqrt d0,d0; bx lr" )
436#elif defined __x86_64__
437double CDECL asm_sqrt(double);
438__ASM_GLOBAL_FUNC( asm_sqrt, "sqrtsd %xmm0, %xmm0; ret" )
439#elif defined __i386__
440double CDECL asm_sqrt(double);
441__ASM_GLOBAL_FUNC( asm_sqrt,
442 "fldl 4(%esp)\n\t"
443 SET_X87_CW(0xc00)
444 "fsqrt\n\t"
446 "ret" )
447#endif
448
449/*********************************************************************
450 * sqrt (MSVCRT.@)
451 */
452double CDECL MSVCRT_sqrt( double x )
453{
454 if (!sqrt_validate(&x, TRUE))
455 return x;
456
457 return asm_sqrt(x);
458}
459
460/*********************************************************************
461 * tanh (MSVCRT.@)
462 */
463#if _MSVCR_VER < 140 /* other versions call tanh() directly */
464double CDECL MSVCRT_tanh( double x )
465{
466 if (isnan( x ))
467 {
468 *(UINT64*)&x |= 0x0008000000000000ULL;
469 return math_error(_DOMAIN, "tanh", x, 0, x);
470 }
471 return tanh( x );
472}
473#endif
474
475#if (defined(__GNUC__) || defined(__clang__)) && defined(__i386__)
476
477#define CREATE_FPU_FUNC1(name, call) \
478 __ASM_GLOBAL_FUNC(name, \
479 "pushl %ebp\n\t" \
480 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
481 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
482 "movl %esp, %ebp\n\t" \
483 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
484 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
485 "fstpl (%esp)\n\t" /* store function argument */ \
486 "fwait\n\t" \
487 "movl $1, %ecx\n\t" /* empty FPU stack */ \
488 "1:\n\t" \
489 "fxam\n\t" \
490 "fstsw %ax\n\t" \
491 "and $0x4500, %ax\n\t" \
492 "cmp $0x4100, %ax\n\t" \
493 "je 2f\n\t" \
494 "fstpl (%esp,%ecx,8)\n\t" \
495 "fwait\n\t" \
496 "incl %ecx\n\t" \
497 "jmp 1b\n\t" \
498 "2:\n\t" \
499 "movl %ecx, -4(%ebp)\n\t" \
500 "call " __ASM_NAME( #call ) "\n\t" \
501 "movl -4(%ebp), %ecx\n\t" \
502 "fstpl (%esp)\n\t" /* save result */ \
503 "3:\n\t" /* restore FPU stack */ \
504 "decl %ecx\n\t" \
505 "fldl (%esp,%ecx,8)\n\t" \
506 "cmpl $0, %ecx\n\t" \
507 "jne 3b\n\t" \
508 "leave\n\t" \
509 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
510 __ASM_CFI(".cfi_same_value %ebp\n\t") \
511 "ret")
512
513#define CREATE_FPU_FUNC2(name, call) \
514 __ASM_GLOBAL_FUNC(name, \
515 "pushl %ebp\n\t" \
516 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") \
517 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") \
518 "movl %esp, %ebp\n\t" \
519 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") \
520 "subl $68, %esp\n\t" /* sizeof(double)*8 + sizeof(int) */ \
521 "fstpl 8(%esp)\n\t" /* store function argument */ \
522 "fwait\n\t" \
523 "fstpl (%esp)\n\t" \
524 "fwait\n\t" \
525 "movl $2, %ecx\n\t" /* empty FPU stack */ \
526 "1:\n\t" \
527 "fxam\n\t" \
528 "fstsw %ax\n\t" \
529 "and $0x4500, %ax\n\t" \
530 "cmp $0x4100, %ax\n\t" \
531 "je 2f\n\t" \
532 "fstpl (%esp,%ecx,8)\n\t" \
533 "fwait\n\t" \
534 "incl %ecx\n\t" \
535 "jmp 1b\n\t" \
536 "2:\n\t" \
537 "movl %ecx, -4(%ebp)\n\t" \
538 "call " __ASM_NAME( #call ) "\n\t" \
539 "movl -4(%ebp), %ecx\n\t" \
540 "fstpl 8(%esp)\n\t" /* save result */ \
541 "3:\n\t" /* restore FPU stack */ \
542 "decl %ecx\n\t" \
543 "fldl (%esp,%ecx,8)\n\t" \
544 "cmpl $1, %ecx\n\t" \
545 "jne 3b\n\t" \
546 "leave\n\t" \
547 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") \
548 __ASM_CFI(".cfi_same_value %ebp\n\t") \
549 "ret")
550
551CREATE_FPU_FUNC1(_CIacos, acos)
552CREATE_FPU_FUNC1(_CIasin, asin)
553CREATE_FPU_FUNC1(_CIatan, atan)
554CREATE_FPU_FUNC2(_CIatan2, atan2)
555CREATE_FPU_FUNC1(_CIcos, cos)
556CREATE_FPU_FUNC1(_CIcosh, cosh)
557CREATE_FPU_FUNC1(_CIexp, exp)
558CREATE_FPU_FUNC2(_CIfmod, fmod)
559CREATE_FPU_FUNC1(_CIlog, log)
560CREATE_FPU_FUNC1(_CIlog10, log10)
561CREATE_FPU_FUNC2(_CIpow, pow)
562CREATE_FPU_FUNC1(_CIsin, sin)
563CREATE_FPU_FUNC1(_CIsinh, sinh)
564CREATE_FPU_FUNC1(_CIsqrt, sqrt)
565CREATE_FPU_FUNC1(_CItan, tan)
566CREATE_FPU_FUNC1(_CItanh, tanh)
567
569 "pushl %ebp\n\t"
570 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
571 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
572 "movl %esp, %ebp\n\t"
573 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
574 "subl $12, %esp\n\t" /* sizeof(LONGLONG) + 2*sizeof(WORD) */
575 "fnstcw (%esp)\n\t"
576 "mov (%esp), %ax\n\t"
577 "or $0xc00, %ax\n\t"
578 "mov %ax, 2(%esp)\n\t"
579 "fldcw 2(%esp)\n\t"
580 "fistpq 4(%esp)\n\t"
581 "fldcw (%esp)\n\t"
582 "movl 4(%esp), %eax\n\t"
583 "movl 8(%esp), %edx\n\t"
584 "leave\n\t"
585 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
586 __ASM_CFI(".cfi_same_value %ebp\n\t")
587 "ret")
588
589#endif /* (defined(__GNUC__) || defined(__clang__)) && defined(__i386__) */
590
591#ifndef __REACTOS__
592/*********************************************************************
593 * _fpclass (MSVCRT.@)
594 */
595int CDECL _fpclass(double num)
596{
597 union { double f; UINT64 i; } u = { num };
598 int e = u.i >> 52 & 0x7ff;
599 int s = u.i >> 63;
600
601 switch (e)
602 {
603 case 0:
604 if (u.i << 1) return s ? _FPCLASS_ND : _FPCLASS_PD;
605 return s ? _FPCLASS_NZ : _FPCLASS_PZ;
606 case 0x7ff:
607 if (u.i << 12) return ((u.i >> 51) & 1) ? _FPCLASS_QNAN : _FPCLASS_SNAN;
608 return s ? _FPCLASS_NINF : _FPCLASS_PINF;
609 default:
610 return s ? _FPCLASS_NN : _FPCLASS_PN;
611 }
612}
613#endif // __REACTOS__
614
615/*********************************************************************
616 * _rotl (MSVCRT.@)
617 */
618unsigned int CDECL MSVCRT__rotl(unsigned int num, int shift)
619{
620 shift &= 31;
621 return (num << shift) | (num >> (32-shift));
622}
623
624/*********************************************************************
625 * _lrotl (MSVCRT.@)
626 */
628{
629 shift &= 0x1f;
630 return (num << shift) | (num >> (32-shift));
631}
632
633/*********************************************************************
634 * _lrotr (MSVCRT.@)
635 */
637{
638 shift &= 0x1f;
639 return (num >> shift) | (num << (32-shift));
640}
641
642/*********************************************************************
643 * _rotr (MSVCRT.@)
644 */
645unsigned int CDECL MSVCRT__rotr(unsigned int num, int shift)
646{
647 shift &= 0x1f;
648 return (num >> shift) | (num << (32-shift));
649}
650
651/*********************************************************************
652 * _rotl64 (MSVCRT.@)
653 */
655{
656 shift &= 63;
657 return (num << shift) | (num >> (64-shift));
658}
659
660/*********************************************************************
661 * _rotr64 (MSVCRT.@)
662 */
664{
665 shift &= 63;
666 return (num >> shift) | (num << (64-shift));
667}
668
669/*********************************************************************
670 * abs (MSVCRT.@)
671 */
672int CDECL abs( int n )
673{
674 return n >= 0 ? n : -n;
675}
676
677/*********************************************************************
678 * labs (MSVCRT.@)
679 */
681{
682 return n >= 0 ? n : -n;
683}
684
685#if _MSVCR_VER>=100
686/*********************************************************************
687 * llabs (MSVCR100.@)
688 */
690{
691 return n >= 0 ? n : -n;
692}
693#endif
694
695#if _MSVCR_VER>=120
696/*********************************************************************
697 * imaxabs (MSVCR120.@)
698 */
700{
701 return n >= 0 ? n : -n;
702}
703#endif
704
705/*********************************************************************
706 * _abs64 (MSVCRT.@)
707 */
708#ifdef _MSC_VER
709#pragma function(_abs64)
710#endif
712{
713 return n >= 0 ? n : -n;
714}
715
716#if defined(__i386__) || defined(__x86_64__)
717#ifdef _MSC_VER
718#define get_mxcsr() _mm_getcsr()
719#define set_mxcsr(val) _mm_setcsr(val)
720#else
721static unsigned int get_mxcsr(void)
722{
723 unsigned int ret;
724#ifdef __arm64ec__
725 extern NTSTATUS (*__os_arm64x_get_x64_information)(ULONG,void*,void*);
726 __os_arm64x_get_x64_information( 0, &ret, NULL );
727#else
728 __asm__ __volatile__( "stmxcsr %0" : "=m" (ret) );
729#endif
730 return ret;
731}
732
733static void set_mxcsr( unsigned int val )
734{
735#ifdef __arm64ec__
736 extern NTSTATUS (*__os_arm64x_set_x64_information)(ULONG,ULONG_PTR,void*);
737 __os_arm64x_set_x64_information( 0, val, NULL );
738#else
739 __asm__ __volatile__( "ldmxcsr %0" : : "m" (val) );
740#endif
741}
742#endif
743
744#ifdef __REACTOS__
746#endif
747static void _setfp_sse( unsigned int *cw, unsigned int cw_mask,
748 unsigned int *sw, unsigned int sw_mask )
749{
750#if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
751 unsigned int old_fpword, fpword = get_mxcsr();
752 unsigned int flags;
753
754 old_fpword = fpword;
755
756 cw_mask &= _MCW_EM | _MCW_RC | _MCW_DN;
757 sw_mask &= _MCW_EM;
758
759 if (sw)
760 {
761 flags = 0;
762 if (fpword & 0x1) flags |= _SW_INVALID;
763 if (fpword & 0x2) flags |= _SW_DENORMAL;
764 if (fpword & 0x4) flags |= _SW_ZERODIVIDE;
765 if (fpword & 0x8) flags |= _SW_OVERFLOW;
766 if (fpword & 0x10) flags |= _SW_UNDERFLOW;
767 if (fpword & 0x20) flags |= _SW_INEXACT;
768
769 *sw = (flags & ~sw_mask) | (*sw & sw_mask);
770 TRACE("sse2 update sw %08x to %08x\n", flags, *sw);
771 fpword &= ~0x3f;
772 if (*sw & _SW_INVALID) fpword |= 0x1;
773 if (*sw & _SW_DENORMAL) fpword |= 0x2;
774 if (*sw & _SW_ZERODIVIDE) fpword |= 0x4;
775 if (*sw & _SW_OVERFLOW) fpword |= 0x8;
776 if (*sw & _SW_UNDERFLOW) fpword |= 0x10;
777 if (*sw & _SW_INEXACT) fpword |= 0x20;
778 *sw = flags;
779 }
780
781 if (cw)
782 {
783 flags = 0;
784 if (fpword & 0x80) flags |= _EM_INVALID;
785 if (fpword & 0x100) flags |= _EM_DENORMAL;
786 if (fpword & 0x200) flags |= _EM_ZERODIVIDE;
787 if (fpword & 0x400) flags |= _EM_OVERFLOW;
788 if (fpword & 0x800) flags |= _EM_UNDERFLOW;
789 if (fpword & 0x1000) flags |= _EM_INEXACT;
790 switch (fpword & 0x6000)
791 {
792 case 0x6000: flags |= _RC_UP|_RC_DOWN; break;
793 case 0x4000: flags |= _RC_UP; break;
794 case 0x2000: flags |= _RC_DOWN; break;
795 }
796 switch (fpword & 0x8040)
797 {
798 case 0x0040: flags |= _DN_FLUSH_OPERANDS_SAVE_RESULTS; break;
799 case 0x8000: flags |= _DN_SAVE_OPERANDS_FLUSH_RESULTS; break;
800 case 0x8040: flags |= _DN_FLUSH; break;
801 }
802
803 *cw = (flags & ~cw_mask) | (*cw & cw_mask);
804 TRACE("sse2 update cw %08x to %08x\n", flags, *cw);
805 fpword &= ~0xffc0;
806 if (*cw & _EM_INVALID) fpword |= 0x80;
807 if (*cw & _EM_DENORMAL) fpword |= 0x100;
808 if (*cw & _EM_ZERODIVIDE) fpword |= 0x200;
809 if (*cw & _EM_OVERFLOW) fpword |= 0x400;
810 if (*cw & _EM_UNDERFLOW) fpword |= 0x800;
811 if (*cw & _EM_INEXACT) fpword |= 0x1000;
812 switch (*cw & _MCW_RC)
813 {
814 case _RC_UP|_RC_DOWN: fpword |= 0x6000; break;
815 case _RC_UP: fpword |= 0x4000; break;
816 case _RC_DOWN: fpword |= 0x2000; break;
817 }
818 switch (*cw & _MCW_DN)
819 {
820 case _DN_FLUSH_OPERANDS_SAVE_RESULTS: fpword |= 0x0040; break;
821 case _DN_SAVE_OPERANDS_FLUSH_RESULTS: fpword |= 0x8000; break;
822 case _DN_FLUSH: fpword |= 0x8040; break;
823 }
824
825 /* clear status word if anything changes */
826 if (fpword != old_fpword && !sw)
827 {
828 TRACE("sse2 clear status word\n");
829 fpword &= ~0x3f;
830 }
831 }
832
833 if (fpword != old_fpword) set_mxcsr( fpword );
834#else
835 FIXME("not implemented\n");
836 if (cw) *cw = 0;
837 if (sw) *sw = 0;
838#endif
839}
840#endif
841
842static void _setfp( unsigned int *cw, unsigned int cw_mask,
843 unsigned int *sw, unsigned int sw_mask )
844{
845#if (defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)) && defined(__i386__)
846 unsigned long oldcw = 0, newcw = 0;
847 unsigned long oldsw = 0, newsw = 0;
848 unsigned int flags;
849
850 cw_mask &= _MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC;
851 sw_mask &= _MCW_EM;
852
853 if (sw)
854 {
855#ifdef _MSC_VER
856 __asm { fstsw newsw }
857#else
858 __asm__ __volatile__( "fstsw %0" : "=m" (newsw) );
859#endif
860 oldsw = newsw;
861
862 flags = 0;
863 if (newsw & 0x1) flags |= _SW_INVALID;
864 if (newsw & 0x2) flags |= _SW_DENORMAL;
865 if (newsw & 0x4) flags |= _SW_ZERODIVIDE;
866 if (newsw & 0x8) flags |= _SW_OVERFLOW;
867 if (newsw & 0x10) flags |= _SW_UNDERFLOW;
868 if (newsw & 0x20) flags |= _SW_INEXACT;
869
870 *sw = (flags & ~sw_mask) | (*sw & sw_mask);
871 TRACE("x86 update sw %08x to %08x\n", flags, *sw);
872 newsw &= ~0x3f;
873 if (*sw & _SW_INVALID) newsw |= 0x1;
874 if (*sw & _SW_DENORMAL) newsw |= 0x2;
875 if (*sw & _SW_ZERODIVIDE) newsw |= 0x4;
876 if (*sw & _SW_OVERFLOW) newsw |= 0x8;
877 if (*sw & _SW_UNDERFLOW) newsw |= 0x10;
878 if (*sw & _SW_INEXACT) newsw |= 0x20;
879 *sw = flags;
880 }
881
882 if (cw)
883 {
884#ifdef _MSC_VER
885 __asm { fstcw newcw }
886#else
887 __asm__ __volatile__( "fstcw %0" : "=m" (newcw) );
888#endif
889 oldcw = newcw;
890
891 flags = 0;
892 if (newcw & 0x1) flags |= _EM_INVALID;
893 if (newcw & 0x2) flags |= _EM_DENORMAL;
894 if (newcw & 0x4) flags |= _EM_ZERODIVIDE;
895 if (newcw & 0x8) flags |= _EM_OVERFLOW;
896 if (newcw & 0x10) flags |= _EM_UNDERFLOW;
897 if (newcw & 0x20) flags |= _EM_INEXACT;
898 switch (newcw & 0xc00)
899 {
900 case 0xc00: flags |= _RC_UP|_RC_DOWN; break;
901 case 0x800: flags |= _RC_UP; break;
902 case 0x400: flags |= _RC_DOWN; break;
903 }
904 switch (newcw & 0x300)
905 {
906 case 0x0: flags |= _PC_24; break;
907 case 0x200: flags |= _PC_53; break;
908 case 0x300: flags |= _PC_64; break;
909 }
910 if (newcw & 0x1000) flags |= _IC_AFFINE;
911
912 *cw = (flags & ~cw_mask) | (*cw & cw_mask);
913 TRACE("x86 update cw %08x to %08x\n", flags, *cw);
914 newcw &= ~0x1f3f;
915 if (*cw & _EM_INVALID) newcw |= 0x1;
916 if (*cw & _EM_DENORMAL) newcw |= 0x2;
917 if (*cw & _EM_ZERODIVIDE) newcw |= 0x4;
918 if (*cw & _EM_OVERFLOW) newcw |= 0x8;
919 if (*cw & _EM_UNDERFLOW) newcw |= 0x10;
920 if (*cw & _EM_INEXACT) newcw |= 0x20;
921 switch (*cw & _MCW_RC)
922 {
923 case _RC_UP|_RC_DOWN: newcw |= 0xc00; break;
924 case _RC_UP: newcw |= 0x800; break;
925 case _RC_DOWN: newcw |= 0x400; break;
926 }
927 switch (*cw & _MCW_PC)
928 {
929 case _PC_64: newcw |= 0x300; break;
930 case _PC_53: newcw |= 0x200; break;
931 case _PC_24: newcw |= 0x0; break;
932 }
933 if (*cw & _IC_AFFINE) newcw |= 0x1000;
934 }
935
936 if (oldsw != newsw && (newsw & 0x3f))
937 {
938 struct {
939 WORD control_word;
940 WORD unused1;
941 WORD status_word;
942 WORD unused2;
943 WORD tag_word;
944 WORD unused3;
945 DWORD instruction_pointer;
946 WORD code_segment;
947 WORD unused4;
948 DWORD operand_addr;
949 WORD data_segment;
950 WORD unused5;
951 } fenv;
952
953 assert(cw);
954
955#ifdef _MSC_VER
956 __asm { fnstenv fenv }
957#else
958 __asm__ __volatile__( "fnstenv %0" : "=m" (fenv) );
959#endif
960 fenv.control_word = newcw;
961 fenv.status_word = newsw;
962#ifdef _MSC_VER
963 __asm { fldenv fenv }
964#else
965 __asm__ __volatile__( "fldenv %0" : : "m" (fenv) : "st", "st(1)",
966 "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)" );
967#endif
968 return;
969 }
970
971 if (oldsw != newsw)
972#ifdef _MSC_VER
973 __asm { fnclex }
974#else
975 __asm__ __volatile__( "fnclex" );
976#endif
977 if (oldcw != newcw)
978#ifdef _MSC_VER
979 __asm { fldcw newcw }
980#else
981 __asm__ __volatile__( "fldcw %0" : : "m" (newcw) );
982#endif
983#elif defined(__x86_64__)
984 _setfp_sse(cw, cw_mask, sw, sw_mask);
985#elif defined(__aarch64__)
986 ULONG_PTR old_fpsr = 0, fpsr = 0, old_fpcr = 0, fpcr = 0;
987 unsigned int flags;
988
989 cw_mask &= _MCW_EM | _MCW_RC;
990 sw_mask &= _MCW_EM;
991
992 if (sw)
993 {
994#ifdef _MSC_VER
995 fpsr = _ReadStatusReg(ARM64_FPSR);
996#else
997 __asm__ __volatile__( "mrs %0, fpsr" : "=r" (fpsr) );
998#endif
999 old_fpsr = fpsr;
1000
1001 flags = 0;
1002 if (fpsr & 0x1) flags |= _SW_INVALID;
1003 if (fpsr & 0x2) flags |= _SW_ZERODIVIDE;
1004 if (fpsr & 0x4) flags |= _SW_OVERFLOW;
1005 if (fpsr & 0x8) flags |= _SW_UNDERFLOW;
1006 if (fpsr & 0x10) flags |= _SW_INEXACT;
1007 if (fpsr & 0x80) flags |= _SW_DENORMAL;
1008
1009 *sw = (flags & ~sw_mask) | (*sw & sw_mask);
1010 TRACE("aarch64 update sw %08x to %08x\n", flags, *sw);
1011 fpsr &= ~0x9f;
1012 if (*sw & _SW_INVALID) fpsr |= 0x1;
1013 if (*sw & _SW_ZERODIVIDE) fpsr |= 0x2;
1014 if (*sw & _SW_OVERFLOW) fpsr |= 0x4;
1015 if (*sw & _SW_UNDERFLOW) fpsr |= 0x8;
1016 if (*sw & _SW_INEXACT) fpsr |= 0x10;
1017 if (*sw & _SW_DENORMAL) fpsr |= 0x80;
1018 *sw = flags;
1019 }
1020
1021 if (cw)
1022 {
1023#ifdef _MSC_VER
1024 fpcr = _ReadStatusReg(ARM64_FPCR);
1025#else
1026 __asm__ __volatile__( "mrs %0, fpcr" : "=r" (fpcr) );
1027#endif
1028 old_fpcr = fpcr;
1029
1030 flags = 0;
1031 if (!(fpcr & 0x100)) flags |= _EM_INVALID;
1032 if (!(fpcr & 0x200)) flags |= _EM_ZERODIVIDE;
1033 if (!(fpcr & 0x400)) flags |= _EM_OVERFLOW;
1034 if (!(fpcr & 0x800)) flags |= _EM_UNDERFLOW;
1035 if (!(fpcr & 0x1000)) flags |= _EM_INEXACT;
1036 if (!(fpcr & 0x8000)) flags |= _EM_DENORMAL;
1037 switch (fpcr & 0xc00000)
1038 {
1039 case 0x400000: flags |= _RC_UP; break;
1040 case 0x800000: flags |= _RC_DOWN; break;
1041 case 0xc00000: flags |= _RC_CHOP; break;
1042 }
1043
1044 *cw = (flags & ~cw_mask) | (*cw & cw_mask);
1045 TRACE("aarch64 update cw %08x to %08x\n", flags, *cw);
1046 fpcr &= ~0xc09f00ul;
1047 if (!(*cw & _EM_INVALID)) fpcr |= 0x100;
1048 if (!(*cw & _EM_ZERODIVIDE)) fpcr |= 0x200;
1049 if (!(*cw & _EM_OVERFLOW)) fpcr |= 0x400;
1050 if (!(*cw & _EM_UNDERFLOW)) fpcr |= 0x800;
1051 if (!(*cw & _EM_INEXACT)) fpcr |= 0x1000;
1052 if (!(*cw & _EM_DENORMAL)) fpcr |= 0x8000;
1053 switch (*cw & _MCW_RC)
1054 {
1055 case _RC_CHOP: fpcr |= 0xc00000; break;
1056 case _RC_UP: fpcr |= 0x400000; break;
1057 case _RC_DOWN: fpcr |= 0x800000; break;
1058 }
1059 }
1060
1061 /* mask exceptions if needed */
1062 if (old_fpcr != fpcr && ~(old_fpcr >> 8) & fpsr & 0x9f != fpsr & 0x9f)
1063 {
1064 ULONG_PTR mask = fpcr & ~0x9f00;
1065#ifdef _MSC_VER
1066 _WriteStatusReg(ARM64_FPCR, mask);
1067#else
1068 __asm__ __volatile__( "msr fpcr, %0" :: "r" (mask) );
1069#endif
1070 }
1071
1072#ifdef _MSC_VER
1073 if (old_fpsr != fpsr)
1074 _WriteStatusReg(ARM64_FPSR, fpsr);
1075 if (old_fpcr != fpcr)
1076 _WriteStatusReg(ARM64_FPCR, fpcr);
1077#else
1078 if (old_fpsr != fpsr)
1079 __asm__ __volatile__( "msr fpsr, %0" :: "r" (fpsr) );
1080 if (old_fpcr != fpcr)
1081 __asm__ __volatile__( "msr fpcr, %0" :: "r" (fpcr) );
1082#endif
1083#elif defined(__arm__)
1084 DWORD old_fpscr, fpscr;
1085 unsigned int flags;
1086
1087 __asm__ __volatile__( "vmrs %0, fpscr" : "=r" (fpscr) );
1088 old_fpscr = fpscr;
1089
1090 cw_mask &= _MCW_EM | _MCW_RC;
1091 sw_mask &= _MCW_EM;
1092
1093 if (sw)
1094 {
1095 flags = 0;
1096 if (fpscr & 0x1) flags |= _SW_INVALID;
1097 if (fpscr & 0x2) flags |= _SW_ZERODIVIDE;
1098 if (fpscr & 0x4) flags |= _SW_OVERFLOW;
1099 if (fpscr & 0x8) flags |= _SW_UNDERFLOW;
1100 if (fpscr & 0x10) flags |= _SW_INEXACT;
1101 if (fpscr & 0x80) flags |= _SW_DENORMAL;
1102
1103 *sw = (flags & ~sw_mask) | (*sw & sw_mask);
1104 TRACE("arm update sw %08x to %08x\n", flags, *sw);
1105 fpscr &= ~0x9f;
1106 if (*sw & _SW_INVALID) fpscr |= 0x1;
1107 if (*sw & _SW_ZERODIVIDE) fpscr |= 0x2;
1108 if (*sw & _SW_OVERFLOW) fpscr |= 0x4;
1109 if (*sw & _SW_UNDERFLOW) fpscr |= 0x8;
1110 if (*sw & _SW_INEXACT) fpscr |= 0x10;
1111 if (*sw & _SW_DENORMAL) fpscr |= 0x80;
1112 *sw = flags;
1113 }
1114
1115 if (cw)
1116 {
1117 flags = 0;
1118 if (!(fpscr & 0x100)) flags |= _EM_INVALID;
1119 if (!(fpscr & 0x200)) flags |= _EM_ZERODIVIDE;
1120 if (!(fpscr & 0x400)) flags |= _EM_OVERFLOW;
1121 if (!(fpscr & 0x800)) flags |= _EM_UNDERFLOW;
1122 if (!(fpscr & 0x1000)) flags |= _EM_INEXACT;
1123 if (!(fpscr & 0x8000)) flags |= _EM_DENORMAL;
1124 switch (fpscr & 0xc00000)
1125 {
1126 case 0x400000: flags |= _RC_UP; break;
1127 case 0x800000: flags |= _RC_DOWN; break;
1128 case 0xc00000: flags |= _RC_CHOP; break;
1129 }
1130
1131 *cw = (flags & ~cw_mask) | (*cw & cw_mask);
1132 TRACE("arm update cw %08x to %08x\n", flags, *cw);
1133 fpscr &= ~0xc09f00ul;
1134 if (!(*cw & _EM_INVALID)) fpscr |= 0x100;
1135 if (!(*cw & _EM_ZERODIVIDE)) fpscr |= 0x200;
1136 if (!(*cw & _EM_OVERFLOW)) fpscr |= 0x400;
1137 if (!(*cw & _EM_UNDERFLOW)) fpscr |= 0x800;
1138 if (!(*cw & _EM_INEXACT)) fpscr |= 0x1000;
1139 if (!(*cw & _EM_DENORMAL)) fpscr |= 0x8000;
1140 switch (*cw & _MCW_RC)
1141 {
1142 case _RC_CHOP: fpscr |= 0xc00000; break;
1143 case _RC_UP: fpscr |= 0x400000; break;
1144 case _RC_DOWN: fpscr |= 0x800000; break;
1145 }
1146 }
1147
1148 if (old_fpscr != fpscr)
1149 __asm__ __volatile__( "vmsr fpscr, %0" :: "r" (fpscr) );
1150#else
1151 FIXME("not implemented\n");
1152 if (cw) *cw = 0;
1153 if (sw) *sw = 0;
1154#endif
1155}
1156
1157/**********************************************************************
1158 * _statusfp2 (MSVCR80.@)
1159 */
1160#if defined(__i386__)
1161void CDECL _statusfp2( unsigned int *x86_sw, unsigned int *sse2_sw )
1162{
1163 if (x86_sw)
1164 _setfp(NULL, 0, x86_sw, 0);
1165 if (!sse2_sw) return;
1166 if (sse2_supported)
1167 _setfp_sse(NULL, 0, sse2_sw, 0);
1168 else *sse2_sw = 0;
1169}
1170#endif
1171
1172/**********************************************************************
1173 * _statusfp (MSVCRT.@)
1174 */
1175unsigned int CDECL _statusfp(void)
1176{
1177 unsigned int flags = 0;
1178#if defined(__i386__)
1179 unsigned int x86_sw, sse2_sw;
1180
1181 _statusfp2( &x86_sw, &sse2_sw );
1182 /* FIXME: there's no definition for ambiguous status, just return all status bits for now */
1183 flags = x86_sw | sse2_sw;
1184#else
1185 _setfp(NULL, 0, &flags, 0);
1186#endif
1187 return flags;
1188}
1189
1190/*********************************************************************
1191 * _clearfp (MSVCRT.@)
1192 */
1193unsigned int CDECL _clearfp(void)
1194{
1195 unsigned int flags = 0;
1196#ifdef __i386__
1197 _setfp(NULL, 0, &flags, _MCW_EM);
1198 if (sse2_supported)
1199 {
1200 unsigned int sse_sw = 0;
1201
1202 _setfp_sse(NULL, 0, &sse_sw, _MCW_EM);
1203 flags |= sse_sw;
1204 }
1205#else
1206 _setfp(NULL, 0, &flags, _MCW_EM);
1207#endif
1208 return flags;
1209}
1210
1211/*********************************************************************
1212 * __fpecode (MSVCRT.@)
1213 */
1214int * CDECL __fpecode(void)
1215{
1216 return &msvcrt_get_thread_data()->fpecode;
1217}
1218
1219#ifndef __REACTOS__
1220/*********************************************************************
1221 * ldexp (MSVCRT.@)
1222 */
1223double CDECL ldexp(double num, int exp)
1224{
1225 double z = scalbn(num, exp);
1226
1227 if (isfinite(num) && !isfinite(z))
1228 return math_error(_OVERFLOW, "ldexp", num, exp, z);
1229 if (num && isfinite(num) && !z)
1230 return math_error(_UNDERFLOW, "ldexp", num, exp, z);
1231 return z;
1232}
1233#endif // __REACTOS__
1234
1235/*********************************************************************
1236 * _cabs (MSVCRT.@)
1237 */
1238double CDECL _cabs(struct _complex num)
1239{
1240 return sqrt(num.x * num.x + num.y * num.y);
1241}
1242
1243/*********************************************************************
1244 * _chgsign (MSVCRT.@)
1245 */
1246double CDECL _chgsign(double num)
1247{
1248 union { double f; UINT64 i; } u = { num };
1249 u.i ^= 1ull << 63;
1250 return u.f;
1251}
1252
1253/*********************************************************************
1254 * __control87_2 (MSVCR80.@)
1255 *
1256 * Not exported by native msvcrt, added in msvcr80.
1257 */
1258#ifdef __i386__
1259int CDECL __control87_2( unsigned int newval, unsigned int mask,
1260 unsigned int *x86_cw, unsigned int *sse2_cw )
1261{
1262 if (x86_cw)
1263 {
1264 *x86_cw = newval;
1265 _setfp(x86_cw, mask, NULL, 0);
1266 }
1267
1268 if (!sse2_cw) return 1;
1269
1270 if (sse2_supported)
1271 {
1272 *sse2_cw = newval;
1273 _setfp_sse(sse2_cw, mask, NULL, 0);
1274 }
1275 else *sse2_cw = 0;
1276
1277 return 1;
1278}
1279#endif
1280
1281/*********************************************************************
1282 * _control87 (MSVCRT.@)
1283 */
1284unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
1285{
1286 unsigned int flags = 0;
1287#if defined(__i386__) && (_MSVCR_VER == 0 || _MSVCR_VER >= 80)
1288 unsigned int sse2_cw;
1289
1290 __control87_2( newval, mask, &flags, &sse2_cw );
1291
1292 if (sse2_supported)
1293 {
1294 if ((flags ^ sse2_cw) & (_MCW_EM | _MCW_RC)) flags |= _EM_AMBIGUOUS;
1295 flags |= sse2_cw;
1296 }
1297#else
1298 flags = newval;
1299 _setfp(&flags, mask, NULL, 0);
1300#endif
1301 return flags;
1302}
1303
1304/*********************************************************************
1305 * _controlfp (MSVCRT.@)
1306 */
1307unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
1308{
1309 return _control87( newval, mask & ~_EM_DENORMAL );
1310}
1311
1312/*********************************************************************
1313 * _set_controlfp (MSVCRT.@)
1314 */
1315void CDECL _set_controlfp( unsigned int newval, unsigned int mask )
1316{
1317 _controlfp( newval, mask );
1318}
1319
1320/*********************************************************************
1321 * _controlfp_s (MSVCRT.@)
1322 */
1323int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
1324{
1325 static const unsigned int all_flags = (_MCW_EM | _MCW_IC | _MCW_RC |
1326 _MCW_PC | _MCW_DN);
1327 unsigned int val;
1328
1329 if (!MSVCRT_CHECK_PMT( !(newval & mask & ~all_flags) ))
1330 {
1331 if (cur) *cur = _controlfp( 0, 0 ); /* retrieve it anyway */
1332 return EINVAL;
1333 }
1334 val = _controlfp( newval, mask );
1335 if (cur) *cur = val;
1336 return 0;
1337}
1338
1339#if _MSVCR_VER >= 140 && (defined(__i386__) || defined(__x86_64__))
1340enum fenv_masks
1341{
1342 FENV_X_INVALID = 0x00100010,
1343 FENV_X_DENORMAL = 0x00200020,
1344 FENV_X_ZERODIVIDE = 0x00080008,
1345 FENV_X_OVERFLOW = 0x00040004,
1346 FENV_X_UNDERFLOW = 0x00020002,
1347 FENV_X_INEXACT = 0x00010001,
1348 FENV_X_AFFINE = 0x00004000,
1349 FENV_X_UP = 0x00800200,
1350 FENV_X_DOWN = 0x00400100,
1351 FENV_X_24 = 0x00002000,
1352 FENV_X_53 = 0x00001000,
1353 FENV_Y_INVALID = 0x10000010,
1354 FENV_Y_DENORMAL = 0x20000020,
1355 FENV_Y_ZERODIVIDE = 0x08000008,
1356 FENV_Y_OVERFLOW = 0x04000004,
1357 FENV_Y_UNDERFLOW = 0x02000002,
1358 FENV_Y_INEXACT = 0x01000001,
1359 FENV_Y_UP = 0x80000200,
1360 FENV_Y_DOWN = 0x40000100,
1361 FENV_Y_FLUSH = 0x00000400,
1362 FENV_Y_FLUSH_SAVE = 0x00000800
1363};
1364
1365/* encodes x87/sse control/status word in ulong */
1366static __msvcrt_ulong fenv_encode(unsigned int x, unsigned int y)
1367{
1368 __msvcrt_ulong ret = 0;
1369
1370#ifdef __i386__
1371 if (x & _EM_INVALID) ret |= FENV_X_INVALID;
1372 if (x & _EM_DENORMAL) ret |= FENV_X_DENORMAL;
1373 if (x & _EM_ZERODIVIDE) ret |= FENV_X_ZERODIVIDE;
1374 if (x & _EM_OVERFLOW) ret |= FENV_X_OVERFLOW;
1375 if (x & _EM_UNDERFLOW) ret |= FENV_X_UNDERFLOW;
1376 if (x & _EM_INEXACT) ret |= FENV_X_INEXACT;
1377 if (x & _IC_AFFINE) ret |= FENV_X_AFFINE;
1378 if (x & _RC_UP) ret |= FENV_X_UP;
1379 if (x & _RC_DOWN) ret |= FENV_X_DOWN;
1380 if (x & _PC_24) ret |= FENV_X_24;
1381 if (x & _PC_53) ret |= FENV_X_53;
1382#endif
1383 x &= ~(_MCW_EM | _MCW_IC | _MCW_RC | _MCW_PC);
1384
1385 if (y & _EM_INVALID) ret |= FENV_Y_INVALID;
1386 if (y & _EM_DENORMAL) ret |= FENV_Y_DENORMAL;
1387 if (y & _EM_ZERODIVIDE) ret |= FENV_Y_ZERODIVIDE;
1388 if (y & _EM_OVERFLOW) ret |= FENV_Y_OVERFLOW;
1389 if (y & _EM_UNDERFLOW) ret |= FENV_Y_UNDERFLOW;
1390 if (y & _EM_INEXACT) ret |= FENV_Y_INEXACT;
1391 if (y & _RC_UP) ret |= FENV_Y_UP;
1392 if (y & _RC_DOWN) ret |= FENV_Y_DOWN;
1393 if (y & _DN_FLUSH) ret |= FENV_Y_FLUSH;
1394 if (y & _DN_FLUSH_OPERANDS_SAVE_RESULTS) ret |= FENV_Y_FLUSH_SAVE;
1395 y &= ~(_MCW_EM | _MCW_IC | _MCW_RC | _MCW_DN);
1396
1397 if(x || y) FIXME("unsupported flags: %x, %x\n", x, y);
1398 return ret;
1399}
1400
1401/* decodes x87/sse control/status word, returns FALSE on error */
1402static BOOL fenv_decode(__msvcrt_ulong enc, unsigned int *x, unsigned int *y)
1403{
1404 *x = *y = 0;
1405 if ((enc & FENV_X_INVALID) == FENV_X_INVALID) *x |= _EM_INVALID;
1406 if ((enc & FENV_X_DENORMAL) == FENV_X_DENORMAL) *x |= _EM_DENORMAL;
1407 if ((enc & FENV_X_ZERODIVIDE) == FENV_X_ZERODIVIDE) *x |= _EM_ZERODIVIDE;
1408 if ((enc & FENV_X_OVERFLOW) == FENV_X_OVERFLOW) *x |= _EM_OVERFLOW;
1409 if ((enc & FENV_X_UNDERFLOW) == FENV_X_UNDERFLOW) *x |= _EM_UNDERFLOW;
1410 if ((enc & FENV_X_INEXACT) == FENV_X_INEXACT) *x |= _EM_INEXACT;
1411 if ((enc & FENV_X_AFFINE) == FENV_X_AFFINE) *x |= _IC_AFFINE;
1412 if ((enc & FENV_X_UP) == FENV_X_UP) *x |= _RC_UP;
1413 if ((enc & FENV_X_DOWN) == FENV_X_DOWN) *x |= _RC_DOWN;
1414 if ((enc & FENV_X_24) == FENV_X_24) *x |= _PC_24;
1415 if ((enc & FENV_X_53) == FENV_X_53) *x |= _PC_53;
1416
1417 if ((enc & FENV_Y_INVALID) == FENV_Y_INVALID) *y |= _EM_INVALID;
1418 if ((enc & FENV_Y_DENORMAL) == FENV_Y_DENORMAL) *y |= _EM_DENORMAL;
1419 if ((enc & FENV_Y_ZERODIVIDE) == FENV_Y_ZERODIVIDE) *y |= _EM_ZERODIVIDE;
1420 if ((enc & FENV_Y_OVERFLOW) == FENV_Y_OVERFLOW) *y |= _EM_OVERFLOW;
1421 if ((enc & FENV_Y_UNDERFLOW) == FENV_Y_UNDERFLOW) *y |= _EM_UNDERFLOW;
1422 if ((enc & FENV_Y_INEXACT) == FENV_Y_INEXACT) *y |= _EM_INEXACT;
1423 if ((enc & FENV_Y_UP) == FENV_Y_UP) *y |= _RC_UP;
1424 if ((enc & FENV_Y_DOWN) == FENV_Y_DOWN) *y |= _RC_DOWN;
1425 if ((enc & FENV_Y_FLUSH) == FENV_Y_FLUSH) *y |= _DN_FLUSH;
1426 if ((enc & FENV_Y_FLUSH_SAVE) == FENV_Y_FLUSH_SAVE) *y |= _DN_FLUSH_OPERANDS_SAVE_RESULTS;
1427
1428 if (fenv_encode(*x, *y) != enc)
1429 {
1430 WARN("can't decode: %lx\n", enc);
1431 return FALSE;
1432 }
1433 return TRUE;
1434}
1435#elif _MSVCR_VER >= 120
1436static __msvcrt_ulong fenv_encode(unsigned int x, unsigned int y)
1437{
1438 if (y & _EM_DENORMAL)
1439 y = (y & ~_EM_DENORMAL) | 0x20;
1440
1441 return x | y;
1442}
1443
1444static BOOL fenv_decode(__msvcrt_ulong enc, unsigned int *x, unsigned int *y)
1445{
1446 if (enc & 0x20)
1447 enc = (enc & ~0x20) | _EM_DENORMAL;
1448
1449 *x = *y = enc;
1450 return TRUE;
1451}
1452#endif
1453
1454#if _MSVCR_VER>=120
1455/*********************************************************************
1456 * fegetenv (MSVCR120.@)
1457 */
1459{
1460#if _MSVCR_VER>=140 && defined(__i386__)
1461 unsigned int x87, sse;
1462 __control87_2(0, 0, &x87, &sse);
1463 env->_Fe_ctl = fenv_encode(x87, sse);
1464 _statusfp2(&x87, &sse);
1465 env->_Fe_stat = fenv_encode(x87, sse);
1466#elif _MSVCR_VER>=140
1467 env->_Fe_ctl = fenv_encode(0, _control87(0, 0));
1468 env->_Fe_stat = fenv_encode(0, _statusfp());
1469#else
1470 env->_Fe_ctl = _controlfp(0, 0) & (_EM_INEXACT | _EM_UNDERFLOW |
1472 env->_Fe_stat = _statusfp();
1473#endif
1474 return 0;
1475}
1476
1477/*********************************************************************
1478 * feupdateenv (MSVCR120.@)
1479 */
1480int CDECL feupdateenv(const fenv_t *env)
1481{
1482 fenv_t set;
1483 fegetenv(&set);
1484 set._Fe_ctl = env->_Fe_ctl;
1485 set._Fe_stat |= env->_Fe_stat;
1486 return fesetenv(&set);
1487}
1488
1489/*********************************************************************
1490 * fetestexcept (MSVCR120.@)
1491 */
1492int CDECL fetestexcept(int flags)
1493{
1494 return _statusfp() & flags;
1495}
1496
1497/*********************************************************************
1498 * fesetexceptflag (MSVCR120.@)
1499 */
1500int CDECL fesetexceptflag(const fexcept_t *status, int excepts)
1501{
1502 fenv_t env;
1503
1504 excepts &= FE_ALL_EXCEPT;
1505 if(!excepts)
1506 return 0;
1507
1508 fegetenv(&env);
1509 env._Fe_stat &= ~fenv_encode(excepts, excepts);
1510 env._Fe_stat |= *status & fenv_encode(excepts, excepts);
1511 return fesetenv(&env);
1512}
1513
1514/*********************************************************************
1515 * feraiseexcept (MSVCR120.@)
1516 */
1517int CDECL feraiseexcept(int flags)
1518{
1519 fenv_t env;
1520
1522 fegetenv(&env);
1523 env._Fe_stat |= fenv_encode(flags, flags);
1524 return fesetenv(&env);
1525}
1526
1527/*********************************************************************
1528 * feclearexcept (MSVCR120.@)
1529 */
1530int CDECL feclearexcept(int flags)
1531{
1532 fenv_t env;
1533
1534 fegetenv(&env);
1536 env._Fe_stat &= ~fenv_encode(flags, flags);
1537 return fesetenv(&env);
1538}
1539
1540/*********************************************************************
1541 * fegetexceptflag (MSVCR120.@)
1542 */
1543int CDECL fegetexceptflag(fexcept_t *status, int excepts)
1544{
1545#if _MSVCR_VER>=140 && defined(__i386__)
1546 unsigned int x87, sse;
1547 _statusfp2(&x87, &sse);
1548 *status = fenv_encode(x87 & excepts, sse & excepts);
1549#else
1550 *status = fenv_encode(0, _statusfp() & excepts);
1551#endif
1552 return 0;
1553}
1554#endif
1555
1556#if _MSVCR_VER>=140
1557/*********************************************************************
1558 * __fpe_flt_rounds (UCRTBASE.@)
1559 */
1560int CDECL __fpe_flt_rounds(void)
1561{
1562 unsigned int fpc = _controlfp(0, 0) & _RC_CHOP;
1563
1564 TRACE("()\n");
1565
1566 switch(fpc) {
1567 case _RC_CHOP: return 0;
1568 case _RC_NEAR: return 1;
1569 case _RC_UP: return 2;
1570 default: return 3;
1571 }
1572}
1573#endif
1574
1575#if _MSVCR_VER>=120
1576
1577/*********************************************************************
1578 * fegetround (MSVCR120.@)
1579 */
1580int CDECL fegetround(void)
1581{
1582 return _controlfp(0, 0) & _MCW_RC;
1583}
1584
1585/*********************************************************************
1586 * fesetround (MSVCR120.@)
1587 */
1588int CDECL fesetround(int round_mode)
1589{
1590 if (round_mode & (~_MCW_RC))
1591 return 1;
1592 _controlfp(round_mode, _MCW_RC);
1593 return 0;
1594}
1595
1596#endif /* _MSVCR_VER>=120 */
1597
1598/*********************************************************************
1599 * _finite (MSVCRT.@)
1600 */
1601int CDECL _finite(double num)
1602{
1603 union { double f; UINT64 i; } u = { num };
1604 return (u.i & ~0ull >> 1) < 0x7ffull << 52;
1605}
1606
1607/*********************************************************************
1608 * _fpreset (MSVCRT.@)
1609 */
1610void CDECL _fpreset(void)
1611{
1612#if (defined(__GNUC__) || defined(__clang__)) && defined(__i386__)
1613 const unsigned int x86_cw = 0x27f;
1614 __asm__ __volatile__( "fninit; fldcw %0" : : "m" (x86_cw) );
1615 if (sse2_supported)
1616 {
1617 unsigned int cw = _MCW_EM, sw = 0;
1618 _setfp_sse(&cw, ~0, &sw, ~0);
1619 }
1620#else
1621 unsigned int cw = _MCW_EM, sw = 0;
1622 _setfp(&cw, ~0, &sw, ~0);
1623#endif
1624}
1625
1626#if _MSVCR_VER>=120
1627/*********************************************************************
1628 * feholdexcept (MSVCR120.@)
1629 */
1631{
1632 TRACE( "(%p)\n", env );
1633 fegetenv(env);
1635}
1636
1637/*********************************************************************
1638 * fesetenv (MSVCR120.@)
1639 */
1640int CDECL fesetenv(const fenv_t *env)
1641{
1642 unsigned int x87_cw, cw, x87_stat, stat;
1643 unsigned int mask;
1644
1645 TRACE( "(%p)\n", env );
1646
1647 if (!env->_Fe_ctl && !env->_Fe_stat) {
1648 _fpreset();
1649 return 0;
1650 }
1651
1652 if (!fenv_decode(env->_Fe_ctl, &x87_cw, &cw))
1653 return 1;
1654 if (!fenv_decode(env->_Fe_stat, &x87_stat, &stat))
1655 return 1;
1656
1657#if _MSVCR_VER >= 140
1658 mask = ~0;
1659#else
1662#endif
1663
1664#ifdef __i386__
1665 _setfp(&x87_cw, mask, &x87_stat, ~0);
1666 if (sse2_supported)
1667 _setfp_sse(&cw, mask, &stat, ~0);
1668 return 0;
1669#else
1670 _setfp(&cw, mask, &stat, ~0);
1671 return 0;
1672#endif
1673}
1674#endif
1675
1676/*********************************************************************
1677 * _isnan (MSVCRT.@)
1678 */
1679int CDECL _isnan(double num)
1680{
1681 union { double f; UINT64 i; } u = { num };
1682 return (u.i & ~0ull >> 1) > 0x7ffull << 52;
1683}
1684
1685#if _MSVCR_VER>=120
1686
1687/*********************************************************************
1688 * rint (MSVCR120.@)
1689 */
1690double CDECL MSVCRT_rint(double x)
1691{
1692 unsigned cw;
1693 double y;
1694
1695 cw = _controlfp(0, 0);
1696 if ((cw & _MCW_PC) != _PC_53)
1698 y = rint(x);
1699 if ((cw & _MCW_PC) != _PC_53)
1700 _controlfp(cw, _MCW_PC);
1701 return y;
1702}
1703
1704/*********************************************************************
1705 * _nearbyint (MSVCR120.@)
1706 *
1707 * Based on musl: src/math/nearbyteint.c
1708 */
1709double CDECL nearbyint(double x)
1710{
1711 BOOL update_cw, update_sw;
1712 unsigned int cw, sw;
1713
1714 _setfp(&cw, 0, &sw, 0);
1715 update_cw = !(cw & _EM_INEXACT);
1716 update_sw = !(sw & _SW_INEXACT);
1717 if (update_cw)
1718 {
1719 cw |= _EM_INEXACT;
1720 _setfp(&cw, _EM_INEXACT, NULL, 0);
1721 }
1722 x = MSVCRT_rint(x);
1723 if (update_cw || update_sw)
1724 {
1725 sw = 0;
1726 cw &= ~_EM_INEXACT;
1727 _setfp(update_cw ? &cw : NULL, _EM_INEXACT,
1728 update_sw ? &sw : NULL, _SW_INEXACT);
1729 }
1730 return x;
1731}
1732
1733/*********************************************************************
1734 * _nearbyintf (MSVCR120.@)
1735 *
1736 * Based on musl: src/math/nearbyteintf.c
1737 */
1738float CDECL nearbyintf(float x)
1739{
1740 BOOL update_cw, update_sw;
1741 unsigned int cw, sw;
1742
1743 _setfp(&cw, 0, &sw, 0);
1744 update_cw = !(cw & _EM_INEXACT);
1745 update_sw = !(sw & _SW_INEXACT);
1746 if (update_cw)
1747 {
1748 cw |= _EM_INEXACT;
1749 _setfp(&cw, _EM_INEXACT, NULL, 0);
1750 }
1751 x = rintf(x);
1752 if (update_cw || update_sw)
1753 {
1754 sw = 0;
1755 cw &= ~_EM_INEXACT;
1756 _setfp(update_cw ? &cw : NULL, _EM_INEXACT,
1757 update_sw ? &sw : NULL, _SW_INEXACT);
1758 }
1759 return x;
1760}
1761
1762#endif /* _MSVCR_VER>=120 */
1763
1764/*********************************************************************
1765 * _ecvt (MSVCRT.@)
1766 */
1767char * CDECL _ecvt( double number, int ndigits, int *decpt, int *sign )
1768{
1769 int prec, len;
1771 /* FIXME: check better for overflow (native supports over 300 chars) */
1772 ndigits = min( ndigits, 80 - 8); /* 8 : space for sign, dec point, "e",
1773 * 4 for exponent and one for
1774 * terminating '\0' */
1775 if (!data->efcvt_buffer)
1776 data->efcvt_buffer = malloc( 80 ); /* ought to be enough */
1777
1778 /* handle cases with zero ndigits or less */
1779 prec = ndigits;
1780 if( prec < 1) prec = 2;
1781 len = _snprintf(data->efcvt_buffer, 80, "%.*le", prec - 1, number);
1782
1783 if (data->efcvt_buffer[0] == '-') {
1784 memmove( data->efcvt_buffer, data->efcvt_buffer + 1, len-- );
1785 *sign = 1;
1786 } else *sign = 0;
1787
1788 /* take the decimal "point away */
1789 if( prec != 1)
1790 memmove( data->efcvt_buffer + 1, data->efcvt_buffer + 2, len - 1 );
1791 /* take the exponential "e" out */
1792 data->efcvt_buffer[ prec] = '\0';
1793 /* read the exponent */
1794 sscanf( data->efcvt_buffer + prec + 1, "%d", decpt);
1795 (*decpt)++;
1796 /* adjust for some border cases */
1797 if( data->efcvt_buffer[0] == '0')/* value is zero */
1798 *decpt = 0;
1799 /* handle cases with zero ndigits or less */
1800 if( ndigits < 1){
1801 if( data->efcvt_buffer[ 0] >= '5')
1802 (*decpt)++;
1803 data->efcvt_buffer[ 0] = '\0';
1804 }
1805 TRACE("out=\"%s\"\n",data->efcvt_buffer);
1806 return data->efcvt_buffer;
1807}
1808
1809/*********************************************************************
1810 * _ecvt_s (MSVCRT.@)
1811 */
1812int CDECL _ecvt_s( char *buffer, size_t length, double number, int ndigits, int *decpt, int *sign )
1813{
1814 int prec, len;
1815 char *result;
1816
1817 if (!MSVCRT_CHECK_PMT(buffer != NULL)) return EINVAL;
1818 if (!MSVCRT_CHECK_PMT(decpt != NULL)) return EINVAL;
1819 if (!MSVCRT_CHECK_PMT(sign != NULL)) return EINVAL;
1820 if (!MSVCRT_CHECK_PMT_ERR( length > 2, ERANGE )) return ERANGE;
1821 if (!MSVCRT_CHECK_PMT_ERR(ndigits < (int)length - 1, ERANGE )) return ERANGE;
1822
1823 /* handle cases with zero ndigits or less */
1824 prec = ndigits;
1825 if( prec < 1) prec = 2;
1826 result = malloc(prec + 8);
1827
1828 len = _snprintf(result, prec + 8, "%.*le", prec - 1, number);
1829 if (result[0] == '-') {
1830 memmove( result, result + 1, len-- );
1831 *sign = 1;
1832 } else *sign = 0;
1833
1834 /* take the decimal "point away */
1835 if( prec != 1)
1836 memmove( result + 1, result + 2, len - 1 );
1837 /* take the exponential "e" out */
1838 result[ prec] = '\0';
1839 /* read the exponent */
1840 sscanf( result + prec + 1, "%d", decpt);
1841 (*decpt)++;
1842 /* adjust for some border cases */
1843 if( result[0] == '0')/* value is zero */
1844 *decpt = 0;
1845 /* handle cases with zero ndigits or less */
1846 if( ndigits < 1){
1847 if( result[ 0] >= '5')
1848 (*decpt)++;
1849 result[ 0] = '\0';
1850 }
1851 memcpy( buffer, result, max(ndigits + 1, 1) );
1852 free( result );
1853 return 0;
1854}
1855
1856/***********************************************************************
1857 * _fcvt (MSVCRT.@)
1858 */
1859char * CDECL _fcvt( double number, int ndigits, int *decpt, int *sign )
1860{
1862 int stop, dec1, dec2;
1863 char *ptr1, *ptr2, *first;
1864 char buf[80]; /* ought to be enough */
1865 char decimal_separator = get_locinfo()->lconv->decimal_point[0];
1866
1867 if (!data->efcvt_buffer)
1868 data->efcvt_buffer = malloc( 80 ); /* ought to be enough */
1869
1870 stop = _snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
1871 ptr1 = buf;
1872 ptr2 = data->efcvt_buffer;
1873 first = NULL;
1874 dec1 = 0;
1875 dec2 = 0;
1876
1877 if (*ptr1 == '-') {
1878 *sign = 1;
1879 ptr1++;
1880 } else *sign = 0;
1881
1882 /* For numbers below the requested resolution, work out where
1883 the decimal point will be rather than finding it in the string */
1884 if (number < 1.0 && number > 0.0) {
1885 dec2 = log10(number + 1e-10);
1886 if (-dec2 <= ndigits) dec2 = 0;
1887 }
1888
1889 /* If requested digits is zero or less, we will need to truncate
1890 * the returned string */
1891 if (ndigits < 1) {
1892 stop += ndigits;
1893 }
1894
1895 while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
1896 while (*ptr1 != '\0' && *ptr1 != decimal_separator) {
1897 if (!first) first = ptr2;
1898 if ((ptr1 - buf) < stop) {
1899 *ptr2++ = *ptr1++;
1900 } else {
1901 ptr1++;
1902 }
1903 dec1++;
1904 }
1905
1906 if (ndigits > 0) {
1907 ptr1++;
1908 if (!first) {
1909 while (*ptr1 == '0') { /* Process leading zeroes */
1910 *ptr2++ = *ptr1++;
1911 dec1--;
1912 }
1913 }
1914 while (*ptr1 != '\0') {
1915 if (!first) first = ptr2;
1916 *ptr2++ = *ptr1++;
1917 }
1918 }
1919
1920 *ptr2 = '\0';
1921
1922 /* We never found a non-zero digit, then our number is either
1923 * smaller than the requested precision, or 0.0 */
1924 if (!first) {
1925 if (number > 0.0) {
1926 first = ptr2;
1927 } else {
1928 first = data->efcvt_buffer;
1929 dec1 = 0;
1930 }
1931 }
1932
1933 *decpt = dec2 ? dec2 : dec1;
1934 return first;
1935}
1936
1937/***********************************************************************
1938 * _fcvt_s (MSVCRT.@)
1939 */
1940int CDECL _fcvt_s(char* outbuffer, size_t size, double number, int ndigits, int *decpt, int *sign)
1941{
1942 int stop, dec1, dec2;
1943 char *ptr1, *ptr2, *first;
1944 char buf[80]; /* ought to be enough */
1945 char decimal_separator = get_locinfo()->lconv->decimal_point[0];
1946
1947 if (!outbuffer || !decpt || !sign || size == 0)
1948 {
1949 *_errno() = EINVAL;
1950 return EINVAL;
1951 }
1952
1953 stop = _snprintf(buf, 80, "%.*f", ndigits < 0 ? 0 : ndigits, number);
1954 ptr1 = buf;
1955 ptr2 = outbuffer;
1956 first = NULL;
1957 dec1 = 0;
1958 dec2 = 0;
1959
1960 if (*ptr1 == '-') {
1961 *sign = 1;
1962 ptr1++;
1963 } else *sign = 0;
1964
1965 /* For numbers below the requested resolution, work out where
1966 the decimal point will be rather than finding it in the string */
1967 if (number < 1.0 && number > 0.0) {
1968 dec2 = log10(number + 1e-10);
1969 if (-dec2 <= ndigits) dec2 = 0;
1970 }
1971
1972 /* If requested digits is zero or less, we will need to truncate
1973 * the returned string */
1974 if (ndigits < 1) {
1975 stop += ndigits;
1976 }
1977
1978 while (*ptr1 == '0') ptr1++; /* Skip leading zeroes */
1979 while (*ptr1 != '\0' && *ptr1 != decimal_separator) {
1980 if (!first) first = ptr2;
1981 if ((ptr1 - buf) < stop) {
1982 if (size > 1) {
1983 *ptr2++ = *ptr1++;
1984 size--;
1985 }
1986 } else {
1987 ptr1++;
1988 }
1989 dec1++;
1990 }
1991
1992 if (ndigits > 0) {
1993 ptr1++;
1994 if (!first) {
1995 while (*ptr1 == '0') { /* Process leading zeroes */
1996 if (number == 0.0 && size > 1) {
1997 *ptr2++ = '0';
1998 size--;
1999 }
2000 ptr1++;
2001 dec1--;
2002 }
2003 }
2004 while (*ptr1 != '\0') {
2005 if (!first) first = ptr2;
2006 if (size > 1) {
2007 *ptr2++ = *ptr1++;
2008 size--;
2009 }
2010 }
2011 }
2012
2013 *ptr2 = '\0';
2014
2015 /* We never found a non-zero digit, then our number is either
2016 * smaller than the requested precision, or 0.0 */
2017 if (!first && (number <= 0.0))
2018 dec1 = 0;
2019
2020 *decpt = dec2 ? dec2 : dec1;
2021 return 0;
2022}
2023
2024/***********************************************************************
2025 * _gcvt (MSVCRT.@)
2026 */
2027char * CDECL _gcvt( double number, int ndigit, char *buff )
2028{
2029 if(!buff) {
2030 *_errno() = EINVAL;
2031 return NULL;
2032 }
2033
2034 if(ndigit < 0) {
2035 *_errno() = ERANGE;
2036 return NULL;
2037 }
2038
2039 sprintf(buff, "%.*g", ndigit, number);
2040 return buff;
2041}
2042
2043/***********************************************************************
2044 * _gcvt_s (MSVCRT.@)
2045 */
2046int CDECL _gcvt_s(char *buff, size_t size, double number, int digits)
2047{
2048 int len;
2049
2050 if(!buff) {
2051 *_errno() = EINVAL;
2052 return EINVAL;
2053 }
2054
2055 if( digits<0 || digits>=size) {
2056 if(size)
2057 buff[0] = '\0';
2058
2059 *_errno() = ERANGE;
2060 return ERANGE;
2061 }
2062
2063 len = _scprintf("%.*g", digits, number);
2064 if(len > size) {
2065 buff[0] = '\0';
2066 *_errno() = ERANGE;
2067 return ERANGE;
2068 }
2069
2070 sprintf(buff, "%.*g", digits, number);
2071 return 0;
2072}
2073
2074#include <stdlib.h> /* div_t, ldiv_t */
2075
2076#ifndef __REACTOS__
2077/*********************************************************************
2078 * div (MSVCRT.@)
2079 * VERSION
2080 * [i386] Windows binary compatible - returns the struct in eax/edx.
2081 */
2082#ifdef __i386__
2083unsigned __int64 CDECL div(int num, int denom)
2084{
2085 union {
2086 div_t div;
2087 unsigned __int64 uint64;
2088 } ret;
2089
2090 ret.div.quot = num / denom;
2091 ret.div.rem = num % denom;
2092 return ret.uint64;
2093}
2094#else
2095/*********************************************************************
2096 * div (MSVCRT.@)
2097 * VERSION
2098 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
2099 */
2100div_t CDECL div(int num, int denom)
2101{
2102 div_t ret;
2103
2104 ret.quot = num / denom;
2105 ret.rem = num % denom;
2106 return ret;
2107}
2108#endif /* ifdef __i386__ */
2109
2110
2111/*********************************************************************
2112 * ldiv (MSVCRT.@)
2113 * VERSION
2114 * [i386] Windows binary compatible - returns the struct in eax/edx.
2115 */
2116#ifdef __i386__
2118{
2119 union {
2120 ldiv_t ldiv;
2121 unsigned __int64 uint64;
2122 } ret;
2123
2124 ret.ldiv.quot = num / denom;
2125 ret.ldiv.rem = num % denom;
2126 return ret.uint64;
2127}
2128#else
2129/*********************************************************************
2130 * ldiv (MSVCRT.@)
2131 * VERSION
2132 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
2133 */
2135{
2136 ldiv_t ret;
2137
2138 ret.quot = num / denom;
2139 ret.rem = num % denom;
2140 return ret;
2141}
2142#endif /* ifdef __i386__ */
2143#endif /* !__REACTOS__ */
2144
2145#if _MSVCR_VER>=100
2146/*********************************************************************
2147 * lldiv (MSVCR100.@)
2148 */
2150{
2151 lldiv_t ret;
2152
2153 ret.quot = num / denom;
2154 ret.rem = num % denom;
2155
2156 return ret;
2157}
2158#endif
2159
2160#ifdef __i386__
2161
2162/*********************************************************************
2163 * _adjust_fdiv (MSVCRT.@)
2164 * Used by the MSVC compiler to work around the Pentium FDIV bug.
2165 */
2166int MSVCRT__adjust_fdiv = 0;
2167
2168/***********************************************************************
2169 * _adj_fdiv_m16i (MSVCRT.@)
2170 *
2171 * NOTE
2172 * I _think_ this function is intended to work around the Pentium
2173 * fdiv bug.
2174 */
2175void __stdcall _adj_fdiv_m16i( short arg )
2176{
2177 TRACE("(): stub\n");
2178}
2179
2180/***********************************************************************
2181 * _adj_fdiv_m32 (MSVCRT.@)
2182 *
2183 * NOTE
2184 * I _think_ this function is intended to work around the Pentium
2185 * fdiv bug.
2186 */
2187void __stdcall _adj_fdiv_m32( unsigned int arg )
2188{
2189 TRACE("(): stub\n");
2190}
2191
2192/***********************************************************************
2193 * _adj_fdiv_m32i (MSVCRT.@)
2194 *
2195 * NOTE
2196 * I _think_ this function is intended to work around the Pentium
2197 * fdiv bug.
2198 */
2199void __stdcall _adj_fdiv_m32i( int arg )
2200{
2201 TRACE("(): stub\n");
2202}
2203
2204/***********************************************************************
2205 * _adj_fdiv_m64 (MSVCRT.@)
2206 *
2207 * NOTE
2208 * I _think_ this function is intended to work around the Pentium
2209 * fdiv bug.
2210 */
2211void __stdcall _adj_fdiv_m64( unsigned __int64 arg )
2212{
2213 TRACE("(): stub\n");
2214}
2215
2216/***********************************************************************
2217 * _adj_fdiv_r (MSVCRT.@)
2218 * FIXME
2219 * This function is likely to have the wrong number of arguments.
2220 *
2221 * NOTE
2222 * I _think_ this function is intended to work around the Pentium
2223 * fdiv bug.
2224 */
2225void _adj_fdiv_r(void)
2226{
2227 TRACE("(): stub\n");
2228}
2229
2230/***********************************************************************
2231 * _adj_fdivr_m16i (MSVCRT.@)
2232 *
2233 * NOTE
2234 * I _think_ this function is intended to work around the Pentium
2235 * fdiv bug.
2236 */
2237void __stdcall _adj_fdivr_m16i( short arg )
2238{
2239 TRACE("(): stub\n");
2240}
2241
2242/***********************************************************************
2243 * _adj_fdivr_m32 (MSVCRT.@)
2244 *
2245 * NOTE
2246 * I _think_ this function is intended to work around the Pentium
2247 * fdiv bug.
2248 */
2249void __stdcall _adj_fdivr_m32( unsigned int arg )
2250{
2251 TRACE("(): stub\n");
2252}
2253
2254/***********************************************************************
2255 * _adj_fdivr_m32i (MSVCRT.@)
2256 *
2257 * NOTE
2258 * I _think_ this function is intended to work around the Pentium
2259 * fdiv bug.
2260 */
2261void __stdcall _adj_fdivr_m32i( int arg )
2262{
2263 TRACE("(): stub\n");
2264}
2265
2266/***********************************************************************
2267 * _adj_fdivr_m64 (MSVCRT.@)
2268 *
2269 * NOTE
2270 * I _think_ this function is intended to work around the Pentium
2271 * fdiv bug.
2272 */
2273void __stdcall _adj_fdivr_m64( unsigned __int64 arg )
2274{
2275 TRACE("(): stub\n");
2276}
2277
2278/***********************************************************************
2279 * _adj_fpatan (MSVCRT.@)
2280 * FIXME
2281 * This function is likely to have the wrong number of arguments.
2282 *
2283 * NOTE
2284 * I _think_ this function is intended to work around the Pentium
2285 * fdiv bug.
2286 */
2287void _adj_fpatan(void)
2288{
2289 TRACE("(): stub\n");
2290}
2291
2292/***********************************************************************
2293 * _adj_fprem (MSVCRT.@)
2294 * FIXME
2295 * This function is likely to have the wrong number of arguments.
2296 *
2297 * NOTE
2298 * I _think_ this function is intended to work around the Pentium
2299 * fdiv bug.
2300 */
2301void _adj_fprem(void)
2302{
2303 TRACE("(): stub\n");
2304}
2305
2306/***********************************************************************
2307 * _adj_fprem1 (MSVCRT.@)
2308 * FIXME
2309 * This function is likely to have the wrong number of arguments.
2310 *
2311 * NOTE
2312 * I _think_ this function is intended to work around the Pentium
2313 * fdiv bug.
2314 */
2315void _adj_fprem1(void)
2316{
2317 TRACE("(): stub\n");
2318}
2319
2320/***********************************************************************
2321 * _adj_fptan (MSVCRT.@)
2322 * FIXME
2323 * This function is likely to have the wrong number of arguments.
2324 *
2325 * NOTE
2326 * I _think_ this function is intended to work around the Pentium
2327 * fdiv bug.
2328 */
2329void _adj_fptan(void)
2330{
2331 TRACE("(): stub\n");
2332}
2333
2334/***********************************************************************
2335 * _safe_fdiv (MSVCRT.@)
2336 * FIXME
2337 * This function is likely to have the wrong number of arguments.
2338 *
2339 * NOTE
2340 * I _think_ this function is intended to work around the Pentium
2341 * fdiv bug.
2342 */
2343void _safe_fdiv(void)
2344{
2345 TRACE("(): stub\n");
2346}
2347
2348/***********************************************************************
2349 * _safe_fdivr (MSVCRT.@)
2350 * FIXME
2351 * This function is likely to have the wrong number of arguments.
2352 *
2353 * NOTE
2354 * I _think_ this function is intended to work around the Pentium
2355 * fdiv bug.
2356 */
2357void _safe_fdivr(void)
2358{
2359 TRACE("(): stub\n");
2360}
2361
2362/***********************************************************************
2363 * _safe_fprem (MSVCRT.@)
2364 * FIXME
2365 * This function is likely to have the wrong number of arguments.
2366 *
2367 * NOTE
2368 * I _think_ this function is intended to work around the Pentium
2369 * fdiv bug.
2370 */
2371void _safe_fprem(void)
2372{
2373 TRACE("(): stub\n");
2374}
2375
2376/***********************************************************************
2377 * _safe_fprem1 (MSVCRT.@)
2378 *
2379 * FIXME
2380 * This function is likely to have the wrong number of arguments.
2381 *
2382 * NOTE
2383 * I _think_ this function is intended to work around the Pentium
2384 * fdiv bug.
2385 */
2386void _safe_fprem1(void)
2387{
2388 TRACE("(): stub\n");
2389}
2390
2391#ifndef __REACTOS__
2392/***********************************************************************
2393 * __libm_sse2_acos (MSVCRT.@)
2394 */
2395void __cdecl __libm_sse2_acos(void)
2396{
2397 double d;
2398 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2399 d = acos( d );
2400 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2401}
2402
2403/***********************************************************************
2404 * __libm_sse2_acosf (MSVCRT.@)
2405 */
2406void __cdecl __libm_sse2_acosf(void)
2407{
2408 float f;
2409 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2410 f = acosf( f );
2411 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2412}
2413
2414/***********************************************************************
2415 * __libm_sse2_asin (MSVCRT.@)
2416 */
2417void __cdecl __libm_sse2_asin(void)
2418{
2419 double d;
2420 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2421 d = asin( d );
2422 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2423}
2424
2425/***********************************************************************
2426 * __libm_sse2_asinf (MSVCRT.@)
2427 */
2428void __cdecl __libm_sse2_asinf(void)
2429{
2430 float f;
2431 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2432 f = asinf( f );
2433 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2434}
2435
2436/***********************************************************************
2437 * __libm_sse2_atan (MSVCRT.@)
2438 */
2439void __cdecl __libm_sse2_atan(void)
2440{
2441 double d;
2442 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2443 d = atan( d );
2444 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2445}
2446
2447/***********************************************************************
2448 * __libm_sse2_atan2 (MSVCRT.@)
2449 */
2450void __cdecl __libm_sse2_atan2(void)
2451{
2452 double d1, d2;
2453 __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
2454 d1 = atan2( d1, d2 );
2455 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
2456}
2457
2458/***********************************************************************
2459 * __libm_sse2_atanf (MSVCRT.@)
2460 */
2461void __cdecl __libm_sse2_atanf(void)
2462{
2463 float f;
2464 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2465 f = atanf( f );
2466 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2467}
2468
2469/***********************************************************************
2470 * __libm_sse2_cos (MSVCRT.@)
2471 */
2472void __cdecl __libm_sse2_cos(void)
2473{
2474 double d;
2475 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2476 d = cos( d );
2477 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2478}
2479
2480/***********************************************************************
2481 * __libm_sse2_cosf (MSVCRT.@)
2482 */
2483void __cdecl __libm_sse2_cosf(void)
2484{
2485 float f;
2486 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2487 f = cosf( f );
2488 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2489}
2490
2491/***********************************************************************
2492 * __libm_sse2_exp (MSVCRT.@)
2493 */
2494void __cdecl __libm_sse2_exp(void)
2495{
2496 double d;
2497 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2498 d = exp( d );
2499 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2500}
2501
2502/***********************************************************************
2503 * __libm_sse2_expf (MSVCRT.@)
2504 */
2505void __cdecl __libm_sse2_expf(void)
2506{
2507 float f;
2508 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2509 f = expf( f );
2510 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2511}
2512
2513/***********************************************************************
2514 * __libm_sse2_log (MSVCRT.@)
2515 */
2516void __cdecl __libm_sse2_log(void)
2517{
2518 double d;
2519 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2520 d = log( d );
2521 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2522}
2523
2524/***********************************************************************
2525 * __libm_sse2_log10 (MSVCRT.@)
2526 */
2527void __cdecl __libm_sse2_log10(void)
2528{
2529 double d;
2530 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2531 d = log10( d );
2532 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2533}
2534
2535/***********************************************************************
2536 * __libm_sse2_log10f (MSVCRT.@)
2537 */
2538void __cdecl __libm_sse2_log10f(void)
2539{
2540 float f;
2541 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2542 f = log10f( f );
2543 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2544}
2545
2546/***********************************************************************
2547 * __libm_sse2_logf (MSVCRT.@)
2548 */
2549void __cdecl __libm_sse2_logf(void)
2550{
2551 float f;
2552 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2553 f = logf( f );
2554 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2555}
2556
2557/***********************************************************************
2558 * __libm_sse2_pow (MSVCRT.@)
2559 */
2560void __cdecl __libm_sse2_pow(void)
2561{
2562 double d1, d2;
2563 __asm__ __volatile__( "movq %%xmm0,%0; movq %%xmm1,%1 " : "=m" (d1), "=m" (d2) );
2564 d1 = pow( d1, d2 );
2565 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d1) );
2566}
2567
2568/***********************************************************************
2569 * __libm_sse2_powf (MSVCRT.@)
2570 */
2571void __cdecl __libm_sse2_powf(void)
2572{
2573 float f1, f2;
2574 __asm__ __volatile__( "movd %%xmm0,%0; movd %%xmm1,%1" : "=g" (f1), "=g" (f2) );
2575 f1 = powf( f1, f2 );
2576 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f1) );
2577}
2578
2579/***********************************************************************
2580 * __libm_sse2_sin (MSVCRT.@)
2581 */
2582void __cdecl __libm_sse2_sin(void)
2583{
2584 double d;
2585 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2586 d = sin( d );
2587 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2588}
2589
2590/***********************************************************************
2591 * __libm_sse2_sinf (MSVCRT.@)
2592 */
2593void __cdecl __libm_sse2_sinf(void)
2594{
2595 float f;
2596 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2597 f = sinf( f );
2598 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2599}
2600
2601/***********************************************************************
2602 * __libm_sse2_tan (MSVCRT.@)
2603 */
2604void __cdecl __libm_sse2_tan(void)
2605{
2606 double d;
2607 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2608 d = tan( d );
2609 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2610}
2611
2612/***********************************************************************
2613 * __libm_sse2_tanf (MSVCRT.@)
2614 */
2615void __cdecl __libm_sse2_tanf(void)
2616{
2617 float f;
2618 __asm__ __volatile__( "movd %%xmm0,%0" : "=g" (f) );
2619 f = tanf( f );
2620 __asm__ __volatile__( "movd %0,%%xmm0" : : "g" (f) );
2621}
2622
2623/***********************************************************************
2624 * __libm_sse2_sqrt_precise (MSVCR110.@)
2625 */
2626void __cdecl __libm_sse2_sqrt_precise(void)
2627{
2628 unsigned int cw;
2629 double d;
2630
2631 __asm__ __volatile__( "movq %%xmm0,%0" : "=m" (d) );
2632 __control87_2(0, 0, NULL, &cw);
2633 if (cw & _MCW_RC)
2634 {
2635 d = sqrt(d);
2636 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2637 return;
2638 }
2639
2640 if (!sqrt_validate(&d, FALSE))
2641 {
2642 __asm__ __volatile__( "movq %0,%%xmm0" : : "m" (d) );
2643 return;
2644 }
2645 __asm__ __volatile__( "sqrtsd %xmm0, %xmm0" );
2646}
2647#endif /* !__REACTOS__ */
2648#endif /* __i386__ */
2649
2650#if _MSVCR_VER>=120
2651
2652/*********************************************************************
2653 * lrint (MSVCR120.@)
2654 */
2655__msvcrt_long CDECL lrint(double x)
2656{
2657 double d;
2658
2659 d = MSVCRT_rint(x);
2660 if ((d < 0 && d != (double)(__msvcrt_long)d)
2661 || (d >= 0 && d != (double)(__msvcrt_ulong)d)) {
2662 *_errno() = EDOM;
2663 return 0;
2664 }
2665 return d;
2666}
2667
2668/*********************************************************************
2669 * lrintf (MSVCR120.@)
2670 */
2672{
2673 float f;
2674
2675 f = rintf(x);
2676 if ((f < 0 && f != (float)(__msvcrt_long)f)
2677 || (f >= 0 && f != (float)(__msvcrt_ulong)f)) {
2678 *_errno() = EDOM;
2679 return 0;
2680 }
2681 return f;
2682}
2683
2684/*********************************************************************
2685 * llrint (MSVCR120.@)
2686 */
2687__int64 CDECL llrint(double x)
2688{
2689 double d;
2690
2691 d = MSVCRT_rint(x);
2692 if ((d < 0 && d != (double)(__int64)d)
2693 || (d >= 0 && d != (double)(unsigned __int64)d)) {
2694 *_errno() = EDOM;
2695 return 0;
2696 }
2697 return d;
2698}
2699
2700/*********************************************************************
2701 * llrintf (MSVCR120.@)
2702 */
2703__int64 CDECL llrintf(float x)
2704{
2705 float f;
2706
2707 f = rintf(x);
2708 if ((f < 0 && f != (float)(__int64)f)
2709 || (f >= 0 && f != (float)(unsigned __int64)f)) {
2710 *_errno() = EDOM;
2711 return 0;
2712 }
2713 return f;
2714}
2715
2716/*********************************************************************
2717 * lround (MSVCR120.@)
2718 *
2719 * Copied from musl: src/math/lround.c
2720 */
2722{
2723 double d = round(x);
2724 if (d != (double)(__msvcrt_long)d) {
2725 *_errno() = EDOM;
2726 return 0;
2727 }
2728 return d;
2729}
2730
2731/*********************************************************************
2732 * lroundf (MSVCR120.@)
2733 *
2734 * Copied from musl: src/math/lroundf.c
2735 */
2737{
2738 float f = roundf(x);
2739 if (f != (float)(__msvcrt_long)f) {
2740 *_errno() = EDOM;
2741 return 0;
2742 }
2743 return f;
2744}
2745
2746/*********************************************************************
2747 * llround (MSVCR120.@)
2748 *
2749 * Copied from musl: src/math/llround.c
2750 */
2751__int64 CDECL llround(double x)
2752{
2753 double d = round(x);
2754 if (d != (double)(__int64)d) {
2755 *_errno() = EDOM;
2756 return 0;
2757 }
2758 return d;
2759}
2760
2761/*********************************************************************
2762 * llroundf (MSVCR120.@)
2763 *
2764 * Copied from musl: src/math/llroundf.c
2765 */
2766__int64 CDECL llroundf(float x)
2767{
2768 float f = roundf(x);
2769 if (f != (float)(__int64)f) {
2770 *_errno() = EDOM;
2771 return 0;
2772 }
2773 return f;
2774}
2775
2776/*********************************************************************
2777 * _dtest (MSVCR120.@)
2778 */
2779short CDECL _dtest(double *x)
2780{
2781 return _dclass(*x);
2782}
2783
2784/*********************************************************************
2785 * _fdtest (MSVCR120.@)
2786 */
2787short CDECL _fdtest(float *x)
2788{
2789 return _fdclass(*x);
2790}
2791
2792/*********************************************************************
2793 * _fdsign (MSVCR120.@)
2794 */
2795int CDECL _fdsign(float x)
2796{
2797 union { float f; UINT32 i; } u = { x };
2798 return (u.i >> 16) & 0x8000;
2799}
2800
2801/*********************************************************************
2802 * _dsign (MSVCR120.@)
2803 */
2804int CDECL _dsign(double x)
2805{
2806 union { double f; UINT64 i; } u = { x };
2807 return (u.i >> 48) & 0x8000;
2808}
2809
2810/*********************************************************************
2811 * _dpcomp (MSVCR120.@)
2812 */
2813int CDECL _dpcomp(double x, double y)
2814{
2815 if(isnan(x) || isnan(y))
2816 return 0;
2817
2818 if(x == y) return 2;
2819 return x < y ? 1 : 4;
2820}
2821
2822/*********************************************************************
2823 * _fdpcomp (MSVCR120.@)
2824 */
2825int CDECL _fdpcomp(float x, float y)
2826{
2827 return _dpcomp(x, y);
2828}
2829
2830/*********************************************************************
2831 * acosh (MSVCR120.@)
2832 */
2833double CDECL MSVCRT_acosh(double x)
2834{
2835 if (x < 1)
2836 {
2837 *_errno() = EDOM;
2839 return NAN;
2840 }
2841 return acosh( x );
2842}
2843
2844/*********************************************************************
2845 * acoshf (MSVCR120.@)
2846 */
2847float CDECL MSVCRT_acoshf(float x)
2848{
2849 if (x < 1)
2850 {
2851 *_errno() = EDOM;
2853 return NAN;
2854 }
2855 return acoshf( x );
2856}
2857
2858/*********************************************************************
2859 * atanh (MSVCR120.@)
2860 */
2861double CDECL MSVCRT_atanh(double x)
2862{
2863 if (fabs(x) > 1)
2864 {
2865 *_errno() = EDOM;
2867 return NAN;
2868 }
2869 return atanh( x );
2870}
2871
2872/*********************************************************************
2873 * atanhf (MSVCR120.@)
2874 */
2875float CDECL MSVCRT_atanhf(float x)
2876{
2877 if (fabs(x) > 1)
2878 {
2879 *_errno() = EDOM;
2881 return NAN;
2882 }
2883 return atanhf( x );
2884}
2885
2886#endif /* _MSVCR_VER>=120 */
2887
2888/*********************************************************************
2889 * _scalb (MSVCRT.@)
2890 * scalbn (MSVCR120.@)
2891 * scalbln (MSVCR120.@)
2892 */
2894{
2895 return ldexp(num, power);
2896}
2897
2898/*********************************************************************
2899 * _scalbf (MSVCRT.@)
2900 * scalbnf (MSVCR120.@)
2901 * scalblnf (MSVCR120.@)
2902 */
2904{
2905 return ldexp(num, power);
2906}
2907
2908#if _MSVCR_VER == 120 /* other versions call remainder() directly */
2909
2910/*********************************************************************
2911 * remainder (MSVCR120.@)
2912 */
2913double CDECL MSVCRT_remainder(double x, double y)
2914{
2915#ifdef __x86_64__
2916 if (isnan(x) || isnan(y)) *_errno() = EDOM;
2917#endif
2918 return remainder(x, y);
2919}
2920
2921/*********************************************************************
2922 * remainderf (MSVCR120.@)
2923 */
2924float CDECL MSVCRT_remainderf(float x, float y)
2925{
2926#ifdef __x86_64__
2927 if (isnan(x) || isnan(y)) *_errno() = EDOM;
2928#endif
2929 return remainderf(x, y);
2930}
2931
2932#endif /* _MSVCR_VER == 120 */
2933
2934#if _MSVCR_VER>=120
2935
2936/*********************************************************************
2937 * _except1 (MSVCR120.@)
2938 * TODO:
2939 * - find meaning of ignored cw and operation bits
2940 * - unk parameter
2941 */
2942double CDECL _except1(DWORD fpe, _FP_OPERATION_CODE op, double arg, double res, DWORD cw, void *unk)
2943{
2944 ULONG_PTR exception_arg;
2945 DWORD exception = 0;
2946 unsigned int fpword = 0;
2948 int raise = 0;
2949
2950 TRACE("(%lx %x %lf %lf %lx %p)\n", fpe, op, arg, res, cw, unk);
2951
2952#ifdef _WIN64
2953 cw = ((cw >> 7) & 0x3f) | ((cw >> 3) & 0xc00);
2954#endif
2955 operation = op << 5;
2956 exception_arg = (ULONG_PTR)&operation;
2957
2958 if (fpe & 0x1) { /* overflow */
2959 if ((fpe == 0x1 && (cw & 0x8)) || (fpe==0x11 && (cw & 0x28))) {
2960 /* 32-bit version also sets SW_INEXACT here */
2961 raise |= FE_OVERFLOW;
2962 if (fpe & 0x10) raise |= FE_INEXACT;
2964 } else {
2966 }
2967 } else if (fpe & 0x2) { /* underflow */
2968 if ((fpe == 0x2 && (cw & 0x10)) || (fpe==0x12 && (cw & 0x30))) {
2970 if (fpe & 0x10) raise |= FE_INEXACT;
2971 res = signbit(res) ? -0.0 : 0.0;
2972 } else {
2974 }
2975 } else if (fpe & 0x4) { /* zerodivide */
2976 if ((fpe == 0x4 && (cw & 0x4)) || (fpe==0x14 && (cw & 0x24))) {
2978 if (fpe & 0x10) raise |= FE_INEXACT;
2979 } else {
2981 }
2982 } else if (fpe & 0x8) { /* invalid */
2983 if (fpe == 0x8 && (cw & 0x1)) {
2984 raise |= FE_INVALID;
2985 } else {
2987 }
2988 } else if (fpe & 0x10) { /* inexact */
2989 if (fpe == 0x10 && (cw & 0x20)) {
2990 raise |= FE_INEXACT;
2991 } else {
2993 }
2994 }
2995
2996 if (exception)
2997 raise = 0;
2999 if (exception)
3000 RaiseException(exception, 0, 1, &exception_arg);
3001
3002 if (cw & 0x1) fpword |= _EM_INVALID;
3003 if (cw & 0x2) fpword |= _EM_DENORMAL;
3004 if (cw & 0x4) fpword |= _EM_ZERODIVIDE;
3005 if (cw & 0x8) fpword |= _EM_OVERFLOW;
3006 if (cw & 0x10) fpword |= _EM_UNDERFLOW;
3007 if (cw & 0x20) fpword |= _EM_INEXACT;
3008 switch (cw & 0xc00)
3009 {
3010 case 0xc00: fpword |= _RC_UP|_RC_DOWN; break;
3011 case 0x800: fpword |= _RC_UP; break;
3012 case 0x400: fpword |= _RC_DOWN; break;
3013 }
3014 switch (cw & 0x300)
3015 {
3016 case 0x0: fpword |= _PC_24; break;
3017 case 0x200: fpword |= _PC_53; break;
3018 case 0x300: fpword |= _PC_64; break;
3019 }
3020 if (cw & 0x1000) fpword |= _IC_AFFINE;
3021 _setfp(&fpword, _MCW_EM | _MCW_RC | _MCW_PC | _MCW_IC, NULL, 0);
3022
3023 return res;
3024}
3025
3026_Dcomplex* CDECL _Cbuild(_Dcomplex *ret, double r, double i)
3027{
3028 ret->_Val[0] = r;
3029 ret->_Val[1] = i;
3030 return ret;
3031}
3032
3033double CDECL MSVCR120_creal(_Dcomplex z)
3034{
3035 return z._Val[0];
3036}
3037
3038#endif /* _MSVCR_VER>=120 */
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
#define stat
Definition: acwin.h:100
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
operation
Definition: copy.c:29
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define __attribute__(x)
Definition: btrfs_drv.h:1197
double CDECL _CIsinh(void)
Definition: ci.c:14
double CDECL _CIatan(void)
Definition: ci.c:54
double CDECL _CIatan2(void)
Definition: ci.c:62
double CDECL _CIasin(void)
Definition: ci.c:38
double CDECL _CIfmod(void)
Definition: ci.c:86
double CDECL _CItanh(void)
Definition: ci.c:30
double CDECL _CIcosh(void)
Definition: ci.c:22
double CDECL _CIacos(void)
Definition: ci.c:46
double CDECL _CIlog10(void)
Definition: ci.c:78
double CDECL _CIexp(void)
Definition: ci.c:70
double CDECL _CItan(void)
Definition: ci.c:6
double CDECL _CIcos(void)
Definition: cicos.c:6
double CDECL _CIlog(void)
Definition: cilog.c:6
double CDECL _CIpow(void)
Definition: cipow.c:6
double CDECL _CIsin(void)
Definition: cisin.c:6
double CDECL _CIsqrt(void)
Definition: cisqrt.c:6
Definition: _set.h:50
_Check_return_ _ACRTIMP int __cdecl _fdsign(_In_ float _X)
Definition: _fdsign.c:14
_Check_return_ _ACRTIMP int __cdecl _dpcomp(_In_ double _X, _In_ double _Y)
_Check_return_ _ACRTIMP int __cdecl _fdpcomp(_In_ float _X, _In_ float _Y)
_Check_return_ _ACRTIMP int __cdecl _dsign(_In_ double _X)
Definition: _dsign.c:14
static LPCWSTR LPCWSTR LPCWSTR env
Definition: db.cpp:171
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
UINT op
Definition: effect.c:235
#define NTSTATUS
Definition: precomp.h:19
#define CDECL
Definition: compat.h:29
VOID WINAPI RaiseException(_In_ DWORD dwExceptionCode, _In_ DWORD dwExceptionFlags, _In_ DWORD nNumberOfArguments, _In_opt_ const ULONG_PTR *lpArguments)
Definition: except.c:700
BOOL WINAPI IsProcessorFeaturePresent(IN DWORD ProcessorFeature)
Definition: sysinfo.c:169
int *CDECL _errno(void)
Definition: errno.c:215
int CDECL raise(int sig)
Definition: except.c:685
#define assert(_expr)
Definition: assert.h:32
long __msvcrt_long
Definition: corecrt.h:167
#define __cdecl
Definition: corecrt.h:121
#define __int64
Definition: corecrt.h:72
#define __stdcall
Definition: corecrt.h:120
unsigned long __msvcrt_ulong
Definition: corecrt.h:168
#define EINVAL
Definition: errno.h:44
#define EDOM
Definition: errno.h:54
#define ERANGE
Definition: errno.h:55
#define FE_ALL_EXCEPT
Definition: fenv.h:21
_ACRTIMP int __cdecl fesetenv(const fenv_t *)
_ACRTIMP int __cdecl fesetexceptflag(const fexcept_t *, int)
#define FE_UNDERFLOW
Definition: fenv.h:17
#define FE_INVALID
Definition: fenv.h:20
_ACRTIMP int __cdecl fegetround(void)
_ACRTIMP int __cdecl fegetenv(fenv_t *)
#define FE_INEXACT
Definition: fenv.h:16
_ACRTIMP int __cdecl fegetexceptflag(fexcept_t *, int)
__msvcrt_ulong fexcept_t
Definition: fenv.h:33
_ACRTIMP int __cdecl feclearexcept(int)
_ACRTIMP int __cdecl fesetround(int)
_ACRTIMP int __cdecl fetestexcept(int)
#define FE_DIVBYZERO
Definition: fenv.h:19
#define FE_OVERFLOW
Definition: fenv.h:18
_ACRTIMP int __cdecl feholdexcept(fenv_t *)
#define _FPCLASS_PZ
Definition: float.h:113
#define _FPCLASS_PD
Definition: float.h:114
#define _IC_AFFINE
Definition: float.h:77
#define _DN_SAVE_OPERANDS_FLUSH_RESULTS
Definition: float.h:89
#define _RC_UP
Definition: float.h:80
#define _MCW_EM
Definition: float.h:64
#define _SW_INEXACT
Definition: float.h:93
#define _FPCLASS_PN
Definition: float.h:115
#define _PC_64
Definition: float.h:85
#define _SW_OVERFLOW
Definition: float.h:95
#define _EM_UNDERFLOW
Definition: float.h:75
#define _FPCLASS_ND
Definition: float.h:111
#define _MCW_PC
Definition: float.h:67
#define _FPCLASS_QNAN
Definition: float.h:108
#define _SW_DENORMAL
Definition: float.h:104
#define _MCW_RC
Definition: float.h:66
#define _EM_ZERODIVIDE
Definition: float.h:73
#define _EM_INEXACT
Definition: float.h:76
#define _EM_OVERFLOW
Definition: float.h:74
#define _MCW_IC
Definition: float.h:65
#define _MCW_DN
Definition: float.h:68
#define _FPCLASS_NINF
Definition: float.h:109
#define _EM_AMBIGUOUS
Definition: float.h:90
#define _FPCLASS_NN
Definition: float.h:110
#define _FPCLASS_SNAN
Definition: float.h:107
#define _EM_INVALID
Definition: float.h:71
#define _PC_24
Definition: float.h:83
_ACRTIMP int __cdecl __fpe_flt_rounds(void)
#define _FPCLASS_NZ
Definition: float.h:112
#define _FPCLASS_PINF
Definition: float.h:116
#define _SW_ZERODIVIDE
Definition: float.h:96
#define _DN_FLUSH
Definition: float.h:87
#define _DN_FLUSH_OPERANDS_SAVE_RESULTS
Definition: float.h:88
#define _EM_DENORMAL
Definition: float.h:72
#define _RC_NEAR
Definition: float.h:82
#define _SW_UNDERFLOW
Definition: float.h:94
#define _RC_DOWN
Definition: float.h:81
#define _RC_CHOP
Definition: float.h:79
#define _SW_INVALID
Definition: float.h:97
#define _PC_53
Definition: float.h:84
_FP_OPERATION_CODE
Definition: fpieee.h:37
_ACRTIMP float __cdecl asinf(float)
Definition: asinf.c:47
_ACRTIMP float __cdecl atanf(float)
Definition: atanf.c:47
_ACRTIMP __int64 __cdecl llrint(double)
Definition: mingw_math.h:395
_ACRTIMP float __cdecl powf(float, float)
Definition: powf.c:14
#define FP_NAN
Definition: math.h:278
#define isfinite(x)
Definition: math.h:363
_ACRTIMP double __cdecl scalbn(double, int)
Definition: scalbn.c:14
#define isnan(x)
Definition: math.h:360
_ACRTIMP double __cdecl cosh(double)
Definition: cosh.c:11
#define FP_ZERO
Definition: math.h:281
_ACRTIMP double __cdecl sqrt(double)
Definition: sqrt.c:5
_ACRTIMP double __cdecl sinh(double)
Definition: sinh.c:50
_ACRTIMP double __cdecl fabs(double)
#define FP_INFINITE
Definition: math.h:277
_ACRTIMP double __cdecl tanh(double)
Definition: tanh.c:46
_ACRTIMP float __cdecl acosf(float)
Definition: acosf.c:47
_ACRTIMP double __cdecl atan(double)
Definition: atan.c:77
_ACRTIMP __msvcrt_long __cdecl lrint(double)
Definition: mingw_math.h:371
_ACRTIMP __int64 __cdecl llrintf(float)
Definition: mingw_math.h:403
_ACRTIMP float __cdecl rintf(float)
Definition: mingw_math.h:357
_ACRTIMP __msvcrt_long __cdecl lround(double)
_ACRTIMP double __cdecl sin(double)
Definition: sin.c:21
_ACRTIMP __int64 __cdecl llroundf(float)
_ACRTIMP float __cdecl cosf(float)
Definition: cosf.c:13
_ACRTIMP float __cdecl nearbyintf(float)
_ACRTIMP float __cdecl sinf(float)
Definition: sinf.c:13
_ACRTIMP short __cdecl _fdtest(float *)
_ACRTIMP __int64 __cdecl llround(double)
#define NAN
Definition: math.h:273
_ACRTIMP float __cdecl remainderf(float, float)
Definition: remainderf.c:60
_ACRTIMP double __cdecl tan(double)
Definition: tan.c:122
#define INFINITY
Definition: math.h:272
_ACRTIMP double __cdecl fmod(double, double)
Definition: fmod.c:18
_ACRTIMP float __cdecl logf(float)
Definition: logf.c:12
_ACRTIMP float __cdecl tanhf(float)
Definition: tanhf.c:49
_ACRTIMP double __cdecl remainder(double, double)
Definition: remainder.c:75
#define signbit(x)
Definition: math.h:362
_ACRTIMP float __cdecl log10f(float)
_ACRTIMP short __cdecl _dtest(double *)
_ACRTIMP double __cdecl asin(double)
Definition: asin.c:31
_ACRTIMP double __cdecl nearbyint(double)
_ACRTIMP float __cdecl roundf(float)
Definition: roundf.c:10
_ACRTIMP float __cdecl tanf(float)
Definition: tanf.c:72
_ACRTIMP float __cdecl atanhf(float)
_ACRTIMP double __cdecl cos(double)
Definition: cos.c:21
_ACRTIMP __msvcrt_long __cdecl lroundf(float)
_ACRTIMP double __cdecl atan2(double, double)
Definition: atan2.c:52
_ACRTIMP __msvcrt_long __cdecl lrintf(float)
Definition: mingw_math.h:379
_ACRTIMP double __cdecl acos(double)
Definition: acos.c:28
_ACRTIMP float __cdecl expf(float)
_ACRTIMP double __cdecl rint(double)
Definition: mingw_math.h:350
_ACRTIMP float __cdecl acoshf(float)
long long intmax_t
Definition: stdint.h:65
_ACRTIMP int __cdecl _scprintf(const char *,...) __WINE_CRT_PRINTF_ATTR(1
_ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl _ACRTIMP int __cdecl sscanf(const char *, const char *,...) __WINE_CRT_SCANF_ATTR(2
static int __cdecl _snprintf(char *buffer, size_t size, const char *format,...) __WINE_CRT_PRINTF_ATTR(3
Definition: stdio.h:507
_ACRTIMP lldiv_t __cdecl lldiv(__int64, __int64)
_ACRTIMP __int64 __cdecl llabs(__int64)
#define SET_X87_CW(MASK)
Definition: math.c:91
int(CDECL * MSVCRT_matherr_func)(struct _exception *)
Definition: math.c:67
#define _DOMAIN
Definition: math.c:62
#define _SING
Definition: math.c:63
int CDECL _controlfp_s(unsigned int *cur, unsigned int newval, unsigned int mask)
Definition: math.c:1323
char *CDECL _gcvt(double number, int ndigit, char *buff)
Definition: math.c:2027
unsigned __int64 CDECL MSVCRT__rotr64(unsigned __int64 num, int shift)
Definition: math.c:663
__msvcrt_ulong CDECL MSVCRT__lrotr(__msvcrt_ulong num, int shift)
Definition: math.c:636
#define _UNDERFLOW
Definition: math.c:65
__msvcrt_ulong CDECL MSVCRT__lrotl(__msvcrt_ulong num, int shift)
Definition: math.c:627
static BOOL sqrtf_validate(float *x)
Definition: math.c:268
void CDECL _set_controlfp(unsigned int newval, unsigned int mask)
Definition: math.c:1315
unsigned int CDECL _statusfp(void)
Definition: math.c:1175
static BOOL sse2_enabled
Definition: math.c:72
float CDECL _chgsignf(float num)
Definition: math.c:203
#define RESET_X87_CW
Definition: math.c:104
void CDECL __setusermatherr(MSVCRT_matherr_func func)
Definition: math.c:159
double CDECL MSVCRT_asin(double x)
Definition: math.c:352
int CDECL _fpclassf(float num)
Definition: math.c:217
short CDECL _fdclass(float x)
int CDECL _matherr(struct _exception *e)
Definition: math.c:119
double CDECL MSVCRT_atan(double x)
Definition: math.c:380
double CDECL MSVCRT_tanh(double x)
Definition: math.c:464
BOOL sse2_supported
Definition: math.c:71
int CDECL _finitef(float num)
Definition: math.c:239
int *CDECL __fpecode(void)
Definition: math.c:1214
double CDECL MSVCRT_exp(double x)
Definition: math.c:391
double CDECL _scalb(double num, __msvcrt_long power)
Definition: math.c:2893
double CDECL _chgsign(double num)
Definition: math.c:1246
unsigned int CDECL _clearfp(void)
Definition: math.c:1193
static MSVCRT_matherr_func MSVCRT_default_matherr_func
Definition: math.c:69
static void _setfp(unsigned int *cw, unsigned int cw_mask, unsigned int *sw, unsigned int sw_mask)
Definition: math.c:842
div_t CDECL div(int num, int denom)
Definition: math.c:2100
static BOOL sqrt_validate(double *x, BOOL update_sw)
Definition: math.c:400
int CDECL _finite(double num)
Definition: math.c:1601
int CDECL _isnanf(float num)
Definition: math.c:248
void CDECL _fpreset(void)
Definition: math.c:1610
int CDECL _isnan(double num)
Definition: math.c:1679
double CDECL _cabs(struct _complex num)
Definition: math.c:1238
float CDECL MSVCRT_atanf(float x)
Definition: math.c:258
unsigned int CDECL _controlfp(unsigned int newval, unsigned int mask)
Definition: math.c:1307
__int64 CDECL _abs64(__int64 n)
Definition: math.c:711
static double ret_nan(BOOL update_sw)
Definition: math.c:84
ldiv_t CDECL ldiv(__msvcrt_long num, __msvcrt_long denom)
Definition: math.c:2134
unsigned int CDECL _control87(unsigned int newval, unsigned int mask)
Definition: math.c:1284
int CDECL _ecvt_s(char *buffer, size_t length, double number, int ndigits, int *decpt, int *sign)
Definition: math.c:1812
char *CDECL _ecvt(double number, int ndigits, int *decpt, int *sign)
Definition: math.c:1767
unsigned int CDECL MSVCRT__rotr(unsigned int num, int shift)
Definition: math.c:645
unsigned __int64 CDECL MSVCRT__rotl64(unsigned __int64 num, int shift)
Definition: math.c:654
double CDECL MSVCRT_sqrt(double x)
Definition: math.c:452
float CDECL MSVCRT_tanhf(float x)
Definition: math.c:319
char *CDECL _fcvt(double number, int ndigits, int *decpt, int *sign)
Definition: math.c:1859
short CDECL _dclass(double x)
unsigned int CDECL MSVCRT__rotl(unsigned int num, int shift)
Definition: math.c:618
double CDECL ldexp(double num, int exp)
Definition: math.c:1223
__msvcrt_long CDECL labs(__msvcrt_long n)
Definition: math.c:680
int CDECL _gcvt_s(char *buff, size_t size, double number, int digits)
Definition: math.c:2046
int CDECL _fcvt_s(char *outbuffer, size_t size, double number, int ndigits, int *decpt, int *sign)
Definition: math.c:1940
double math_error(int type, const char *name, double arg1, double arg2, double retval)
Definition: math.c:125
float CDECL MSVCRT_sqrtf(float x)
Definition: math.c:303
#define _OVERFLOW
Definition: math.c:64
int CDECL _fpclass(double num)
Definition: math.c:595
float CDECL _scalbf(float num, __msvcrt_long power)
Definition: math.c:2903
int CDECL _set_SSE2_enable(int flag)
Definition: math.c:168
thread_data_t *CDECL msvcrt_get_thread_data(void)
Definition: ucrt_tls_sup.c:59
#define MSVCRT_CHECK_PMT(x)
Definition: msvcrt.h:378
#define MSVCRT_CHECK_PMT_ERR(x, err)
Definition: msvcrt.h:377
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
return ret
Definition: mutex.c:147
unsigned long long uint64
Definition: platform.h:18
#define ULONG_PTR
Definition: config.h:101
#define abs(i)
Definition: fconv.c:206
void _safe_fdiv(void)
Definition: fdivbug.c:69
void __stdcall _adj_fdivr_m32(unsigned int arg)
Definition: fdivbug.c:24
void __stdcall _adj_fdiv_m32i(int arg)
Definition: fdivbug.c:9
void __stdcall _adj_fdiv_m32(unsigned int arg)
Definition: fdivbug.c:5
void _adj_fpatan(void)
Definition: fdivbug.c:39
void _adj_fptan(void)
Definition: fdivbug.c:64
void _safe_fprem1(void)
Definition: fdivbug.c:84
void _safe_fprem(void)
Definition: fdivbug.c:79
void __stdcall _adj_fdivr_m16i(short arg)
Definition: fdivbug.c:49
void __stdcall _adj_fdivr_m64(unsigned __int64 arg)
Definition: fdivbug.c:34
void __stdcall _adj_fdivr_m32i(int arg)
Definition: fdivbug.c:29
void _safe_fdivr(void)
Definition: fdivbug.c:74
void _adj_fprem(void)
Definition: fdivbug.c:54
void __stdcall _adj_fdiv_m16i(short arg)
Definition: fdivbug.c:44
void _adj_fprem1(void)
Definition: fdivbug.c:59
void _adj_fdiv_r(void)
Definition: fdivbug.c:19
void __stdcall _adj_fdiv_m64(unsigned __int64 arg)
Definition: fdivbug.c:14
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
int __cdecl _set_FMA3_enable(int flag)
double log10(double x)
Definition: freeldr.c:191
double pow(double x, double y)
Definition: freeldr.c:179
double atanh(double x)
Definition: fun_ieee.c:63
double acosh(double x)
Definition: fun_ieee.c:54
FxCollectionEntry * cur
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLenum func
Definition: glext.h:6028
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
GLuint res
Definition: glext.h:9613
GLsizeiptr size
Definition: glext.h:5919
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
const GLubyte * c
Definition: glext.h:8905
GLenum GLint GLuint mask
Definition: glext.h:6028
GLbitfield flags
Definition: glext.h:7161
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
GLfloat f
Definition: glext.h:7540
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLdouble GLdouble z
Definition: glext.h:5874
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
static const int digits[]
Definition: decode.c:71
#define d
Definition: ke_i.h:81
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define debugstr_a
Definition: kernel32.h:31
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_cosf(__m128 Xmm0)
Definition: libm_sse2.c:86
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_log10f(__m128 Xmm0)
Definition: libm_sse2.c:134
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_atan(__m128d Xmm0)
Definition: libm_sse2.c:55
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_acos(__m128d Xmm0)
Definition: libm_sse2.c:23
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_asin(__m128d Xmm0)
Definition: libm_sse2.c:39
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_asinf(__m128 Xmm0)
Definition: libm_sse2.c:46
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_cos(__m128d Xmm0)
Definition: libm_sse2.c:79
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_pow(__m128d Xmm0, __m128d Xmm1)
Definition: libm_sse2.c:143
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_tan(__m128d Xmm0)
Definition: libm_sse2.c:175
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_atanf(__m128 Xmm0)
Definition: libm_sse2.c:62
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_sinf(__m128 Xmm0)
Definition: libm_sse2.c:166
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_expf(__m128 Xmm0)
Definition: libm_sse2.c:102
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_logf(__m128 Xmm0)
Definition: libm_sse2.c:118
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_powf(__m128 Xmm0, __m128 Xmm1)
Definition: libm_sse2.c:151
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_atan2(__m128d Xmm0, __m128d Xmm1)
Definition: libm_sse2.c:71
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_acosf(__m128 Xmm0)
Definition: libm_sse2.c:30
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_exp(__m128d Xmm0)
Definition: libm_sse2.c:95
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_log(__m128d Xmm0)
Definition: libm_sse2.c:111
__ATTRIBUTE_SSE2__ __m128 __libm_sse2_tanf(__m128 Xmm0)
Definition: libm_sse2.c:182
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_log10(__m128d Xmm0)
Definition: libm_sse2.c:127
__ATTRIBUTE_SSE2__ __m128d __libm_sse2_sin(__m128d Xmm0)
Definition: libm_sse2.c:159
#define sign(x)
Definition: mapdesc.cc:613
#define EXCEPTION_FLT_UNDERFLOW
Definition: minwinbase.h:55
#define EXCEPTION_FLT_OVERFLOW
Definition: minwinbase.h:53
#define EXCEPTION_FLT_INEXACT_RESULT
Definition: minwinbase.h:51
#define EXCEPTION_FLT_INVALID_OPERATION
Definition: minwinbase.h:52
#define EXCEPTION_FLT_DIVIDE_BY_ZERO
Definition: minwinbase.h:50
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
#define sprintf
Definition: sprintf.c:45
float power
Definition: d3drm.c:3533
static unsigned int number
Definition: dsound.c:1479
void msvcrt_init_math(void)
static size_t double int ndigits
Definition: printf.c:52
static size_t double int int * decpt
Definition: printf.c:52
static unsigned long fenv_encode(unsigned int e)
Definition: misc.c:1379
#define shift
Definition: input.c:3280
DWORD exp
Definition: msg.c:18625
#define __ASM_GLOBAL_FUNC(name, code)
Definition: port.h:201
#define min(a, b)
Definition: monoChain.cc:55
#define sqrtf(x)
Definition: mymath.h:59
@ sse
Definition: optimize.h:107
__asm__(".p2align 4, 0x90\n" ".seh_proc __seh2_global_filter_func\n" "__seh2_global_filter_func:\n" "\tsub %rbp, %rax\n" "\tpush %rbp\n" "\t.seh_pushreg %rbp\n" "\tpush %rbx\n" "\t.seh_pushreg %rbx\n" "\tpush %rdi\n" "\t.seh_pushreg %rdi\n" "\tpush %rsi\n" "\t.seh_pushreg %rsi\n" "\tpush %r12\n" "\t.seh_pushreg %r12\n" "\tpush %r13\n" "\t.seh_pushreg %r13\n" "\tpush %r14\n" "\t.seh_pushreg %r14\n" "\tpush %r15\n" "\t.seh_pushreg %r15\n" "\tsub $40, %rsp\n" "\t.seh_stackalloc 40\n" "\t.seh_endprologue\n" "\tsub %rax, %rdx\n" "\tmov %rdx, %rbp\n" "\tjmp *%r8\n" "__seh2_global_filter_func_exit:\n" "\t.p2align 4\n" "\tadd $40, %rsp\n" "\tpop %r15\n" "\tpop %r14\n" "\tpop %r13\n" "\tpop %r12\n" "\tpop %rsi\n" "\tpop %rdi\n" "\tpop %rbx\n" "\tpop %rbp\n" "\tret\n" "\t.seh_endproc")
int __cdecl feraiseexcept(int excepts)
int __cdecl feupdateenv(const fenv_t *)
intmax_t __cdecl imaxabs(intmax_t j)
Definition: inttypes.h:277
_ACRTIMP _Dcomplex __cdecl _Cbuild(_In_ double _Re, _In_ double _Im)
#define f2(x, y, z)
Definition: sha1.c:31
#define f1(x, y, z)
Definition: sha1.c:30
#define log(outFile, fmt,...)
Definition: util.h:15
static const char *static const char const char DWORD void DWORD *static const char const char DWORD void DWORD *static const char DWORD DWORD void * buff
Definition: shcore.c:41
#define TRACE(s)
Definition: solgame.cpp:4
Definition: math.h:42
Definition: stdlib.h:47
Definition: stdlib.h:52
Definition: fenv.h:28
Definition: name.c:39
Definition: stat.h:66
Definition: ps.c:97
#define max(a, b)
Definition: svc.c:63
SYMCRYPT_ECURVE_INFO_PRECOMP sw
uint64_t ULONGLONG
Definition: typedefs.h:67
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
int retval
Definition: wcstombs.cpp:91
#define round(x)
Definition: opentype.c:51
#define __ASM_CFI(str)
Definition: asm.h:39
#define get_locinfo()
Definition: winesup.h:25
#define PF_XMMI64_INSTRUCTIONS_AVAILABLE
Definition: ketypes.h:186
#define __ATTRIBUTE_SSE__
Definition: xmmintrin.h:68