source: trunk/src/msvcrt/math.c

Last change on this file was 10005, checked in by sandervl, 22 years ago

PF: MSVCRT update

File size: 26.6 KB
RevLine 
[9633]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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#ifdef __WIN32OS2__
21#include <emxheader.h>
[10005]22#include <stdlib.h>
23#include <string.h>
24#include <math.h>
25extern double logb(double);
26extern double scalb(double,double);
[9633]27#else
28#include "config.h"
29#endif
30
31#include "msvcrt.h"
32#include "msvcrt/errno.h"
33
34#define __USE_ISOC9X 1
35#define __USE_ISOC99 1
[10005]36
[9633]37#ifdef HAVE_IEEEFP_H
38#include <ieeefp.h>
39#endif
40
41#include "msvcrt/stdlib.h"
42
43#include "wine/debug.h"
44
45WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
46
47#ifndef HAVE_FINITE
48#ifndef finite /* Could be a macro */
49#ifdef isfinite
[10005]50#define finite(x) isfinite(x)
[9633]51#else
52#define finite(x) (!isnan(x)) /* At least catch some cases */
53#endif
54#endif
55#endif
56
57#ifndef signbit
58#define signbit(x) 0
59#endif
60
61/* fpclass constants */
62#define _FPCLASS_SNAN 1
63#define _FPCLASS_QNAN 2
64#define _FPCLASS_NINF 4
65#define _FPCLASS_NN 8
66#define _FPCLASS_ND 16
67#define _FPCLASS_NZ 32
68#define _FPCLASS_PZ 64
69#define _FPCLASS_PD 128
70#define _FPCLASS_PN 256
71#define _FPCLASS_PINF 512
72
73/* _statusfp bit flags */
74#define _SW_INEXACT 0x1
75#define _SW_UNDERFLOW 0x2
76#define _SW_OVERFLOW 0x4
77#define _SW_ZERODIVIDE 0x8
78#define _SW_INVALID 0x10
79#define _SW_DENORMAL 0x80000
80
81/* _controlfp masks and bitflags - x86 only so far*/
82#ifdef __i386__
83#define _MCW_EM 0x8001f
84#define _EM_INEXACT 0x1
85#define _EM_UNDERFLOW 0x2
86#define _EM_OVERFLOW 0x4
87#define _EM_ZERODIVIDE 0x8
88#define _EM_INVALID 0x10
89
90#define _MCW_RC 0x300
91#define _RC_NEAR 0x0
92#define _RC_DOWN 0x100
93#define _RC_UP 0x200
94#define _RC_CHOP 0x300
95
96#define _MCW_PC 0x30000
97#define _PC_64 0x0
98#define _PC_53 0x10000
99#define _PC_24 0x20000
100
101#define _MCW_IC 0x40000
102#define _IC_AFFINE 0x40000
103#define _IC_PROJECTIVE 0x0
104
105#define _EM_DENORMAL 0x80000
106#endif
107
108typedef struct __MSVCRT_complex
109{
110 double real;
111 double imaginary;
112} MSVCRT_complex;
113
114typedef struct __MSVCRT_exception
115{
116 int type;
117 char *name;
118 double arg1;
119 double arg2;
120 double retval;
121} MSVCRT_exception;
122
123
124typedef int (*MSVCRT_matherr_func)(MSVCRT_exception *);
125
126static MSVCRT_matherr_func MSVCRT_default_matherr_func = NULL;
127
128#if defined(__GNUC__) && defined(__i386__)
129
130#define FPU_DOUBLE(var) double var; \
131 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var) : )
132#define FPU_DOUBLES(var1,var2) double var1,var2; \
133 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var2) : ); \
134 __asm__ __volatile__( "fstpl %0;fwait" : "=m" (var1) : )
135
136/*********************************************************************
137 * _CIacos (MSVCRT.@)
138 */
139double _CIacos(void)
140{
141 FPU_DOUBLE(x);
[10005]142 dprintf(("MSVCRT: _CIacos"));
[9633]143 if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
144 return acos(x);
145}
146
147/*********************************************************************
148 * _CIasin (MSVCRT.@)
149 */
150double _CIasin(void)
151{
152 FPU_DOUBLE(x);
[10005]153 dprintf(("MSVCRT: _CIacos"));
[9633]154 if (x < -1.0 || x > 1.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
155 return asin(x);
156}
157
158/*********************************************************************
159 * _CIatan (MSVCRT.@)
160 */
161double _CIatan(void)
162{
163 FPU_DOUBLE(x);
[10005]164 dprintf(("MSVCRT: _CIacos"));
[9633]165 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
166 return atan(x);
167}
168
169/*********************************************************************
170 * _CIatan2 (MSVCRT.@)
171 */
172double _CIatan2(void)
173{
174 FPU_DOUBLES(x,y);
[10005]175 dprintf(("MSVCRT: _CIacos"));
[9633]176 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
177 return atan2(x,y);
178}
179
180/*********************************************************************
181 * _CIcos (MSVCRT.@)
182 */
183double _CIcos(void)
184{
185 FPU_DOUBLE(x);
[10005]186 dprintf(("MSVCRT: _CIacos"));
[9633]187 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
188 return cos(x);
189}
190
191/*********************************************************************
192 * _CIcosh (MSVCRT.@)
193 */
194double _CIcosh(void)
195{
196 FPU_DOUBLE(x);
[10005]197 dprintf(("MSVCRT: _CIacos"));
[9633]198 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
199 return cosh(x);
200}
201
202/*********************************************************************
203 * _CIexp (MSVCRT.@)
204 */
205double _CIexp(void)
206{
207 FPU_DOUBLE(x);
[10005]208 dprintf(("MSVCRT: _CIacos"));
[9633]209 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
210 return exp(x);
211}
212
213/*********************************************************************
214 * _CIfmod (MSVCRT.@)
215 */
216double _CIfmod(void)
217{
218 FPU_DOUBLES(x,y);
[10005]219 dprintf(("MSVCRT: _CIfmod %f %f",x,y));
220 if (!finite(x) || !finite(y)) { *MSVCRT__errno() = MSVCRT_EDOM; dprintf(("ERROR!")); }
221 dprintf(("MSVCRT: _CIfmod returning %f",fmod(x,y)));
[9633]222 return fmod(x,y);
223}
224
225/*********************************************************************
226 * _CIlog (MSVCRT.@)
227 */
228double _CIlog(void)
229{
230 FPU_DOUBLE(x);
[10005]231 dprintf(("MSVCRT: _CIacos"));
[9633]232 if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
233 if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
234 return log(x);
235}
236
237/*********************************************************************
238 * _CIlog10 (MSVCRT.@)
239 */
240double _CIlog10(void)
241{
242 FPU_DOUBLE(x);
[10005]243 dprintf(("MSVCRT: _CIacos"));
[9633]244 if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
245 if (x == 0.0) *MSVCRT__errno() = MSVCRT_ERANGE;
246 return log10(x);
247}
248
249/*********************************************************************
250 * _CIpow (MSVCRT.@)
251 */
252double _CIpow(void)
253{
254 double z;
255 FPU_DOUBLES(x,y);
[10005]256 dprintf(("MSVCRT: _CIacos"));
[9633]257 /* FIXME: If x < 0 and y is not integral, set EDOM */
258 z = pow(x,y);
259 if (!finite(z)) *MSVCRT__errno() = MSVCRT_EDOM;
260 return z;
261}
262
263/*********************************************************************
264 * _CIsin (MSVCRT.@)
265 */
266double _CIsin(void)
267{
268 FPU_DOUBLE(x);
[10005]269 dprintf(("MSVCRT: _CIacos"));
[9633]270 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
271 return sin(x);
272}
273
274/*********************************************************************
275 * _CIsinh (MSVCRT.@)
276 */
277double _CIsinh(void)
278{
279 FPU_DOUBLE(x);
[10005]280 dprintf(("MSVCRT: _CIacos"));
[9633]281 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
282 return sinh(x);
283}
284
285/*********************************************************************
286 * _CIsqrt (MSVCRT.@)
287 */
288double _CIsqrt(void)
289{
290 FPU_DOUBLE(x);
[10005]291 dprintf(("MSVCRT: _CIacos"));
[9633]292 if (x < 0.0 || !finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
293 return sqrt(x);
294}
295
296/*********************************************************************
297 * _CItan (MSVCRT.@)
298 */
299double _CItan(void)
300{
301 FPU_DOUBLE(x);
[10005]302 dprintf(("MSVCRT: _CIacos"));
[9633]303 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
304 return tan(x);
305}
306
307/*********************************************************************
308 * _CItanh (MSVCRT.@)
309 */
310double _CItanh(void)
311{
312 FPU_DOUBLE(x);
[10005]313 dprintf(("MSVCRT: _CIacos"));
[9633]314 if (!finite(x)) *MSVCRT__errno() = MSVCRT_EDOM;
315 return tanh(x);
316}
317
318#else /* defined(__GNUC__) && defined(__i386__) */
319
320/* The above cannot be called on non x86 platforms, stub them for linking */
321
322#define IX86_ONLY(func) double func(void) { return 0.0; }
323
324IX86_ONLY(_CIacos)
325IX86_ONLY(_CIasin)
326IX86_ONLY(_CIatan)
327IX86_ONLY(_CIatan2)
328IX86_ONLY(_CIcos)
329IX86_ONLY(_CIcosh)
330IX86_ONLY(_CIexp)
331IX86_ONLY(_CIfmod)
332IX86_ONLY(_CIlog)
333IX86_ONLY(_CIlog10)
334IX86_ONLY(_CIpow)
335IX86_ONLY(_CIsin)
336IX86_ONLY(_CIsinh)
337IX86_ONLY(_CIsqrt)
338IX86_ONLY(_CItan)
339IX86_ONLY(_CItanh)
340
341#endif /* defined(__GNUC__) && defined(__i386__) */
342
343/*********************************************************************
344 * _fpclass (MSVCRT.@)
345 */
346int _fpclass(double num)
347{
[10005]348 dprintf(("MSVCRT: _fpclass"));
[9633]349#if defined(HAVE_FPCLASS) || defined(fpclass)
350 switch (fpclass( num ))
351 {
352 case FP_SNAN: return _FPCLASS_SNAN;
353 case FP_QNAN: return _FPCLASS_QNAN;
354 case FP_NINF: return _FPCLASS_NINF;
355 case FP_PINF: return _FPCLASS_PINF;
356 case FP_NDENORM: return _FPCLASS_ND;
357 case FP_PDENORM: return _FPCLASS_PD;
358 case FP_NZERO: return _FPCLASS_NZ;
359 case FP_PZERO: return _FPCLASS_PZ;
360 case FP_NNORM: return _FPCLASS_NN;
361 case FP_PNORM: return _FPCLASS_PN;
362 }
363 return _FPCLASS_PN;
364#elif defined (fpclassify)
365 switch (fpclassify( num ))
366 {
367 case FP_NAN: return _FPCLASS_QNAN;
368 case FP_INFINITE: return signbit(num) ? _FPCLASS_NINF : _FPCLASS_PINF;
369 case FP_SUBNORMAL: return signbit(num) ?_FPCLASS_ND : _FPCLASS_PD;
370 case FP_ZERO: return signbit(num) ? _FPCLASS_NZ : _FPCLASS_PZ;
371 }
372 return signbit(num) ? _FPCLASS_NN : _FPCLASS_PN;
373#else
374 if (!finite(num))
375 return _FPCLASS_QNAN;
376 return num == 0.0 ? _FPCLASS_PZ : (num < 0 ? _FPCLASS_NN : _FPCLASS_PN);
377#endif
378}
379
380/*********************************************************************
381 * _rotl (MSVCRT.@)
382 */
[10005]383unsigned int MSVCRT__rotl(unsigned int num, int shift)
[9633]384{
385 shift &= 31;
386 return (num << shift) | (num >> (32-shift));
387}
388
389/*********************************************************************
390 * _logb (MSVCRT.@)
391 */
392double _logb(double num)
393{
[10005]394 dprintf(("MSVCRT: _logb"));
[9633]395 if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
396 return logb(num);
397}
398
399/*********************************************************************
400 * _lrotl (MSVCRT.@)
401 */
[10005]402unsigned long MSVCRT__lrotl(unsigned long num, int shift)
[9633]403{
[10005]404 dprintf(("MSVCRT: _lrotl"));
[9633]405 shift &= 0x1f;
406 return (num << shift) | (num >> (32-shift));
407}
408
409/*********************************************************************
410 * _lrotr (MSVCRT.@)
411 */
[10005]412unsigned long MSVCRT__lrotr(unsigned long num, int shift)
[9633]413{
[10005]414 dprintf(("MSVCRT: _lrotr"));
[9633]415 shift &= 0x1f;
416 return (num >> shift) | (num << (32-shift));
417}
418
419/*********************************************************************
420 * _rotr (MSVCRT.@)
421 */
[10005]422unsigned int MSVCRT__rotr(unsigned int num, int shift)
[9633]423{
[10005]424 dprintf(("MSVCRT: _rotr"));
[9633]425 shift &= 0x1f;
426 return (num >> shift) | (num << (32-shift));
427}
428
429/*********************************************************************
430 * _scalb (MSVCRT.@)
431 */
432double _scalb(double num, long power)
433{
434 /* Note - Can't forward directly as libc expects y as double */
[10005]435 dprintf(("MSVCRT: _scalb"));
[9633]436 double dblpower = (double)power;
437 if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
438 return scalb(num, dblpower);
439}
440
441/*********************************************************************
442 * _matherr (MSVCRT.@)
443 */
[10005]444int MSVCRT__matherr(MSVCRT_exception *e)
[9633]445{
446 if (e)
447 TRACE("(%p = %d, %s, %g %g %g)\n",e, e->type, e->name, e->arg1, e->arg2,
448 e->retval);
449 else
450 TRACE("(null)\n");
451 if (MSVCRT_default_matherr_func)
452 return MSVCRT_default_matherr_func(e);
453 ERR(":Unhandled math error!\n");
454 return 0;
455}
456
457/*********************************************************************
458 * __setusermatherr (MSVCRT.@)
459 */
460void MSVCRT___setusermatherr(MSVCRT_matherr_func func)
461{
462 MSVCRT_default_matherr_func = func;
463 TRACE(":new matherr handler %p\n", func);
464}
465
466/**********************************************************************
467 * _statusfp (MSVCRT.@)
468 */
469unsigned int _statusfp(void)
470{
471 unsigned int retVal = 0;
472#if defined(__GNUC__) && defined(__i386__)
473 unsigned int fpword;
474
475 __asm__ __volatile__( "fstsw %0" : "=m" (fpword) : );
476 if (fpword & 0x1) retVal |= _SW_INVALID;
477 if (fpword & 0x2) retVal |= _SW_DENORMAL;
478 if (fpword & 0x4) retVal |= _SW_ZERODIVIDE;
479 if (fpword & 0x8) retVal |= _SW_OVERFLOW;
480 if (fpword & 0x10) retVal |= _SW_UNDERFLOW;
481 if (fpword & 0x20) retVal |= _SW_INEXACT;
482#else
483 FIXME(":Not implemented!\n");
484#endif
485 return retVal;
486}
487
488/*********************************************************************
489 * _clearfp (MSVCRT.@)
490 */
491unsigned int _clearfp(void)
492{
493 unsigned int retVal = _statusfp();
494#if defined(__GNUC__) && defined(__i386__)
495 __asm__ __volatile__( "fnclex" );
496#else
497 FIXME(":Not Implemented\n");
498#endif
499 return retVal;
500}
501
502/*********************************************************************
503 * ldexp (MSVCRT.@)
504 */
505double MSVCRT_ldexp(double num, long exp)
506{
507 double z = ldexp(num,exp);
[10005]508 dprintf(("MSVCRT: ldexpp"));
[9633]509 if (!finite(z))
510 *MSVCRT__errno() = MSVCRT_ERANGE;
511 else if (z == 0 && signbit(z))
512 z = 0.0; /* Convert -0 -> +0 */
513 return z;
514}
515
516/*********************************************************************
517 * _cabs (MSVCRT.@)
518 */
[10005]519double MSVCRT__cabs(MSVCRT_complex num)
[9633]520{
[10005]521 dprintf(("MSVCRT: _cabs"));
[9633]522 return sqrt(num.real * num.real + num.imaginary * num.imaginary);
523}
524
525/*********************************************************************
526 * _chgsign (MSVCRT.@)
527 */
528double _chgsign(double num)
529{
[10005]530 dprintf(("MSVCRT: _chgsign"));
[9633]531 /* FIXME: +-infinity,Nan not tested */
532 return -num;
533}
534
535/*********************************************************************
536 * _control87 (MSVCRT.@)
537 */
[10005]538unsigned int MSVCRT__control87(unsigned int newval, unsigned int mask)
[9633]539{
540#if defined(__GNUC__) && defined(__i386__)
541 unsigned int fpword = 0;
542 unsigned int flags = 0;
543
544 TRACE("(%08x, %08x): Called\n", newval, mask);
545
546 /* Get fp control word */
547 __asm__ __volatile__( "fstcw %0" : "=m" (fpword) : );
548
549 TRACE("Control word before : %08x\n", fpword);
550
551 /* Convert into mask constants */
552 if (fpword & 0x1) flags |= _EM_INVALID;
553 if (fpword & 0x2) flags |= _EM_DENORMAL;
554 if (fpword & 0x4) flags |= _EM_ZERODIVIDE;
555 if (fpword & 0x8) flags |= _EM_OVERFLOW;
556 if (fpword & 0x10) flags |= _EM_UNDERFLOW;
557 if (fpword & 0x20) flags |= _EM_INEXACT;
558 switch(fpword & 0xC00) {
559 case 0xC00: flags |= _RC_UP|_RC_DOWN; break;
560 case 0x800: flags |= _RC_UP; break;
561 case 0x400: flags |= _RC_DOWN; break;
562 }
563 switch(fpword & 0x300) {
564 case 0x0: flags |= _PC_24; break;
565 case 0x200: flags |= _PC_53; break;
566 case 0x300: flags |= _PC_64; break;
567 }
568 if (fpword & 0x1000) flags |= _IC_AFFINE;
569
570 /* Mask with parameters */
571 flags = (flags & ~mask) | (newval & mask);
572
573 /* Convert (masked) value back to fp word */
574 fpword = 0;
575 if (flags & _EM_INVALID) fpword |= 0x1;
576 if (flags & _EM_DENORMAL) fpword |= 0x2;
577 if (flags & _EM_ZERODIVIDE) fpword |= 0x4;
578 if (flags & _EM_OVERFLOW) fpword |= 0x8;
579 if (flags & _EM_UNDERFLOW) fpword |= 0x10;
580 if (flags & _EM_INEXACT) fpword |= 0x20;
581 switch(flags & (_RC_UP | _RC_DOWN)) {
582 case _RC_UP|_RC_DOWN: fpword |= 0xC00; break;
583 case _RC_UP: fpword |= 0x800; break;
584 case _RC_DOWN: fpword |= 0x400; break;
585 }
586 switch (flags & (_PC_24 | _PC_53)) {
587 case _PC_64: fpword |= 0x300; break;
588 case _PC_53: fpword |= 0x200; break;
589 case _PC_24: fpword |= 0x0; break;
590 }
591 if (flags & _IC_AFFINE) fpword |= 0x1000;
592
593 TRACE("Control word after : %08x\n", fpword);
594
595 /* Put fp control word */
596 __asm__ __volatile__( "fldcw %0" : : "m" (fpword) );
597
598 return flags;
599#else
600 FIXME(":Not Implemented!\n");
601 return 0;
602#endif
603}
604
605/*********************************************************************
606 * _controlfp (MSVCRT.@)
607 */
608unsigned int _controlfp(unsigned int newval, unsigned int mask)
609{
610#ifdef __i386__
[10005]611 return MSVCRT__control87( newval, mask & ~_EM_DENORMAL );
[9633]612#else
613 FIXME(":Not Implemented!\n");
614 return 0;
615#endif
616}
617
618/*********************************************************************
619 * _copysign (MSVCRT.@)
620 */
[10005]621double MSVCRT__copysign(double num, double sign)
[9633]622{
[10005]623 dprintf(("MSVCRT: _CIacos"));
[9633]624 /* FIXME: Behaviour for Nan/Inf? */
625 if (sign < 0.0)
626 return num < 0.0 ? num : -num;
627 return num < 0.0 ? -num : num;
628}
629
630/*********************************************************************
631 * _finite (MSVCRT.@)
632 */
633int _finite(double num)
634{
[10005]635 dprintf(("MSVCRT: _finite for %f returns %d",num, finite(num)?1:0));
[9633]636 return (finite(num)?1:0); /* See comment for _isnan() */
637}
638
639/*********************************************************************
640 * _fpreset (MSVCRT.@)
641 */
[10005]642void MSVCRT__fpreset(void)
[9633]643{
644#if defined(__GNUC__) && defined(__i386__)
645 __asm__ __volatile__( "fninit" );
646#else
647 FIXME(":Not Implemented!\n");
648#endif
649}
650
651/*********************************************************************
652 * _isnan (MSVCRT.@)
653 */
654INT _isnan(double num)
655{
656 /* Some implementations return -1 for true(glibc), msvcrt/crtdll return 1.
657 * Do the same, as the result may be used in calculations
658 */
[10005]659 dprintf(("MSVCRT: _isnan for %f returns %d",num, isnan(num)?1:0));
[9633]660 return isnan(num) ? 1 : 0;
661}
662
663/*********************************************************************
664 * _y0 (MSVCRT.@)
665 */
[10005]666double MSVCRT__y0(double num)
[9633]667{
668 double retval;
[10005]669 dprintf(("MSVCRT: _CIacos"));
[9633]670 if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
671 retval = y0(num);
672 if (_fpclass(retval) == _FPCLASS_NINF)
673 {
674 *MSVCRT__errno() = MSVCRT_EDOM;
675 retval = sqrt(-1);
676 }
677 return retval;
678}
679
680/*********************************************************************
681 * _y1 (MSVCRT.@)
682 */
[10005]683double MSVCRT__y1(double num)
[9633]684{
685 double retval;
[10005]686 dprintf(("MSVCRT: _CIacos"));
[9633]687 if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
688 retval = y1(num);
689 if (_fpclass(retval) == _FPCLASS_NINF)
690 {
691 *MSVCRT__errno() = MSVCRT_EDOM;
692 retval = sqrt(-1);
693 }
694 return retval;
695}
696
697/*********************************************************************
698 * _yn (MSVCRT.@)
699 */
[10005]700double MSVCRT__yn(int order, double num)
[9633]701{
702 double retval;
[10005]703 dprintf(("MSVCRT: _CIacos"));
[9633]704 if (!finite(num)) *MSVCRT__errno() = MSVCRT_EDOM;
705 retval = yn(order,num);
706 if (_fpclass(retval) == _FPCLASS_NINF)
707 {
708 *MSVCRT__errno() = MSVCRT_EDOM;
709 retval = sqrt(-1);
710 }
711 return retval;
712}
713
714/*********************************************************************
715 * _nextafter (MSVCRT.@)
716 */
[10005]717double MSVCRT__nextafter(double num, double next)
[9633]718{
719 double retval;
[10005]720 dprintf(("MSVCRT: _CIacos"));
[9633]721 if (!finite(num) || !finite(next)) *MSVCRT__errno() = MSVCRT_EDOM;
[10005]722 retval = MSVCRT__nextafter(num,next);
[9633]723 return retval;
724}
725
[10005]726/*********************************************************************
727 * _ecvt (MSVCRT.@)
728 */
729char *_ecvt( double number, int ndigits, int *decpt, int *sign )
730{
731 MSVCRT_thread_data *data = msvcrt_get_thread_data();
732 char *dec;
733
734 if (!data->efcvt_buffer)
735 data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
736
737 _snprintf(data->efcvt_buffer, 80, "%.*e", ndigits /* FIXME wrong */, number);
738 *sign = (number < 0);
739 dec = strchr(data->efcvt_buffer, '.');
740 *decpt = (dec) ? dec - data->efcvt_buffer : -1;
741 return data->efcvt_buffer;
742}
743
744/***********************************************************************
745 * _fcvt (MSVCRT.@)
746 */
747char *_fcvt( double number, int ndigits, int *decpt, int *sign )
748{
749 MSVCRT_thread_data *data = msvcrt_get_thread_data();
750 char *dec;
751
752 if (!data->efcvt_buffer)
753 data->efcvt_buffer = MSVCRT_malloc( 80 ); /* ought to be enough */
754
755 _snprintf(data->efcvt_buffer, 80, "%.*e", ndigits, number);
756 *sign = (number < 0);
757 dec = strchr(data->efcvt_buffer, '.');
758 *decpt = (dec) ? dec - data->efcvt_buffer : -1;
759 return data->efcvt_buffer;
760}
761
762/***********************************************************************
763 * _gcvt (MSVCRT.@)
764 *
765 * FIXME: uses both E and F.
766 */
767char *MSVCRT__gcvt( double number, int ndigit, char *buff )
768{
769 sprintf(buff, "%.*E", ndigit, number);
770 return buff;
771}
772
[9633]773#include <stdlib.h> /* div_t, ldiv_t */
774
775/*********************************************************************
776 * div (MSVCRT.@)
777 * VERSION
778 * [i386] Windows binary compatible - returns the struct in eax/edx.
779 */
780#ifdef __i386__
[10005]781long long MSVCRT_div(int num, int denom)
[9633]782{
[10005]783 long long retval;
[9633]784 div_t dt = div(num,denom);
[10005]785 dprintf(("MSVCRT: div"));
786 retval = ((long long)dt.rem << 32) | dt.quot;
[9633]787 return retval;
788}
789#else
790/*********************************************************************
791 * div (MSVCRT.@)
792 * VERSION
793 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
794 */
795MSVCRT_div_t MSVCRT_div(int num, int denom)
796{
797 div_t dt = div(num,denom);
798 MSVCRT_div_t ret;
799 ret.quot = dt.quot;
800 ret.rem = dt.rem;
801
802 return ret;
803
804}
805#endif /* ifdef __i386__ */
806
807
808/*********************************************************************
809 * ldiv (MSVCRT.@)
810 * VERSION
811 * [i386] Windows binary compatible - returns the struct in eax/edx.
812 */
813#ifdef __i386__
814ULONGLONG MSVCRT_ldiv(long num, long denom)
815{
816 ULONGLONG retval;
817 ldiv_t ldt = ldiv(num,denom);
[10005]818 dprintf(("MSVCRT: ldiv"));
[9633]819 retval = ((ULONGLONG)ldt.rem << 32) | (ULONG)ldt.quot;
820 return retval;
821}
822#else
823/*********************************************************************
824 * ldiv (MSVCRT.@)
825 * VERSION
826 * [!i386] Non-x86 can't run win32 apps so we don't need binary compatibility
827 */
828MSVCRT_ldiv_t MSVCRT_ldiv(long num, long denom)
829{
830 ldiv_t result = ldiv(num,denom);
831
832 MSVCRT_ldiv_t ret;
833 ret.quot = result.quot;
834 ret.rem = result.rem;
835
836 return ret;
837}
838#endif /* ifdef __i386__ */
839
840/***********************************************************************
841 * _adj_fdiv_m16i (MSVCRT.@)
842 * FIXME
843 * This function is likely to have the wrong number of arguments.
844 *
845 * NOTE
846 * I _think_ this function is intended to work around the Pentium
847 * fdiv bug.
848 */
849void _adj_fdiv_m16i(void)
850{
851 TRACE("(): stub\n");
852}
853
854/***********************************************************************
855 * _adj_fdiv_m32 (MSVCRT.@)
856 * FIXME
857 * This function is likely to have the wrong number of arguments.
858 *
859 * NOTE
860 * I _think_ this function is intended to work around the Pentium
861 * fdiv bug.
862 */
863void _adj_fdiv_m32(void)
864{
865 TRACE("(): stub\n");
866}
867
868/***********************************************************************
869 * _adj_fdiv_m32i (MSVCRT.@)
870 * FIXME
871 * This function is likely to have the wrong number of arguments.
872 *
873 * NOTE
874 * I _think_ this function is intended to work around the Pentium
875 * fdiv bug.
876 */
877void _adj_fdiv_m32i(void)
878{
879 TRACE("(): stub\n");
880}
881
882/***********************************************************************
883 * _adj_fdiv_m64 (MSVCRT.@)
884 * FIXME
885 * This function is likely to have the wrong number of arguments.
886 *
887 * NOTE
888 * I _think_ this function is intended to work around the Pentium
889 * fdiv bug.
890 */
891void _adj_fdiv_m64(void)
892{
893 TRACE("(): stub\n");
894}
895
896/***********************************************************************
897 * _adj_fdiv_r (MSVCRT.@)
898 * FIXME
899 * This function is likely to have the wrong number of arguments.
900 *
901 * NOTE
902 * I _think_ this function is intended to work around the Pentium
903 * fdiv bug.
904 */
905void _adj_fdiv_r(void)
906{
907 TRACE("(): stub\n");
908}
909
910/***********************************************************************
911 * _adj_fdivr_m16i (MSVCRT.@)
912 * FIXME
913 * This function is likely to have the wrong number of arguments.
914 *
915 * NOTE
916 * I _think_ this function is intended to work around the Pentium
917 * fdiv bug.
918 */
919void _adj_fdivr_m16i(void)
920{
921 TRACE("(): stub\n");
922}
923
924/***********************************************************************
925 * _adj_fdivr_m32 (MSVCRT.@)
926 * FIXME
927 * This function is likely to have the wrong number of arguments.
928 *
929 * NOTE
930 * I _think_ this function is intended to work around the Pentium
931 * fdiv bug.
932 */
933void _adj_fdivr_m32(void)
934{
935 TRACE("(): stub\n");
936}
937
938/***********************************************************************
939 * _adj_fdivr_m32i (MSVCRT.@)
940 * FIXME
941 * This function is likely to have the wrong number of arguments.
942 *
943 * NOTE
944 * I _think_ this function is intended to work around the Pentium
945 * fdiv bug.
946 */
947void _adj_fdivr_m32i(void)
948{
949 TRACE("(): stub\n");
950}
951
952/***********************************************************************
953 * _adj_fdivr_m64 (MSVCRT.@)
954 * FIXME
955 * This function is likely to have the wrong number of arguments.
956 *
957 * NOTE
958 * I _think_ this function is intended to work around the Pentium
959 * fdiv bug.
960 */
961void _adj_fdivr_m64(void)
962{
963 TRACE("(): stub\n");
964}
965
966/***********************************************************************
967 * _adj_fpatan (MSVCRT.@)
968 * FIXME
969 * This function is likely to have the wrong number of arguments.
970 *
971 * NOTE
972 * I _think_ this function is intended to work around the Pentium
973 * fdiv bug.
974 */
975void _adj_fpatan(void)
976{
977 TRACE("(): stub\n");
978}
979
980/***********************************************************************
981 * _adj_fprem (MSVCRT.@)
982 * FIXME
983 * This function is likely to have the wrong number of arguments.
984 *
985 * NOTE
986 * I _think_ this function is intended to work around the Pentium
987 * fdiv bug.
988 */
989void _adj_fprem(void)
990{
991 TRACE("(): stub\n");
992}
993
994/***********************************************************************
995 * _adj_fprem1 (MSVCRT.@)
996 * FIXME
997 * This function is likely to have the wrong number of arguments.
998 *
999 * NOTE
1000 * I _think_ this function is intended to work around the Pentium
1001 * fdiv bug.
1002 */
1003void _adj_fprem1(void)
1004{
1005 TRACE("(): stub\n");
1006}
1007
1008/***********************************************************************
1009 * _adj_fptan (MSVCRT.@)
1010 * FIXME
1011 * This function is likely to have the wrong number of arguments.
1012 *
1013 * NOTE
1014 * I _think_ this function is intended to work around the Pentium
1015 * fdiv bug.
1016 */
1017void _adj_fptan(void)
1018{
1019 TRACE("(): stub\n");
1020}
1021
1022/***********************************************************************
1023 * _adjust_fdiv (MSVCRT.@)
1024 * FIXME
1025 * I _think_ this function should be a variable indicating whether
1026 * Pentium fdiv bug safe code should be used.
1027 */
1028void _adjust_fdiv(void)
1029{
1030 TRACE("(): stub\n");
1031}
1032
1033/***********************************************************************
1034 * _safe_fdiv (MSVCRT.@)
1035 * FIXME
1036 * This function is likely to have the wrong number of arguments.
1037 *
1038 * NOTE
1039 * I _think_ this function is intended to work around the Pentium
1040 * fdiv bug.
1041 */
1042void _safe_fdiv(void)
1043{
1044 TRACE("(): stub\n");
1045}
1046
1047/***********************************************************************
1048 * _safe_fdivr (MSVCRT.@)
1049 * FIXME
1050 * This function is likely to have the wrong number of arguments.
1051 *
1052 * NOTE
1053 * I _think_ this function is intended to work around the Pentium
1054 * fdiv bug.
1055 */
1056void _safe_fdivr(void)
1057{
1058 TRACE("(): stub\n");
1059}
1060
1061/***********************************************************************
1062 * _safe_fprem (MSVCRT.@)
1063 * FIXME
1064 * This function is likely to have the wrong number of arguments.
1065 *
1066 * NOTE
1067 * I _think_ this function is intended to work around the Pentium
1068 * fdiv bug.
1069 */
1070void _safe_fprem(void)
1071{
1072 TRACE("(): stub\n");
1073}
1074
1075/***********************************************************************
1076 * _safe_fprem1 (MSVCRT.@)
1077 *
1078 * FIXME
1079 * This function is likely to have the wrong number of arguments.
1080 *
1081 * NOTE
1082 * I _think_ this function is intended to work around the Pentium
1083 * fdiv bug.
1084 */
1085void _safe_fprem1(void)
1086{
1087 TRACE("(): stub\n");
1088}
[10005]1089
1090
1091double MSVCRT_atof (__const__ char * str)
1092{
1093 double res;
1094 res = atof(str);
1095 dprintf(("MSVCRT: _atof - convert %s - result %f",str,res));
1096 return res;
1097}
Note: See TracBrowser for help on using the repository browser.