1:
2: // Copyright (c) 1999-2011 by Digital Mars
3: // All Rights Reserved
4: // written by Walter Bright
5: // http://www.digitalmars.com
6:
7: #include "port.h"
8: #if __DMC__
9: #include <math.h>
10: #include <float.h>
11: #include <fp.h>
12: #include <time.h>
13: #include <stdlib.h>
14: #include <string.h>
15:
16: double Port::nan = NAN;
17: double Port::infinity = INFINITY;
18: double Port::dbl_max = DBL_MAX;
19: double Port::dbl_min = DBL_MIN;
20: long double Port::ldbl_max = LDBL_MAX;
21:
22: int Port::isNan(double r)
23: {
24: return ::isnan(r);
25: }
26:
27: int Port::isNan(long double r)
28: {
29: return ::isnan(r);
30: }
31:
32: int Port::isSignallingNan(double r)
33: {
34: /* A signalling NaN is a NaN with 0 as the most significant bit of
35: * its significand, which is bit 51 of 0..63 for 64 bit doubles.
36: */
37: return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
38: }
39:
40: int Port::isSignallingNan(long double r)
41: {
42: /* A signalling NaN is a NaN with 0 as the most significant bit of
43: * its significand, which is bit 62 of 0..79 for 80 bit reals.
44: */
45: return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
46: }
47:
48: int Port::isFinite(double r)
49: {
50: return ::isfinite(r);
51: }
52:
53: int Port::isInfinity(double r)
54: {
55: return (::fpclassify(r) == FP_INFINITE);
56: }
57:
58: int Port::Signbit(double r)
59: {
60: return ::signbit(r);
61: }
62:
63: double Port::floor(double d)
64: {
65: return ::floor(d);
66: }
67:
68: double Port::pow(double x, double y)
69: {
70: return ::pow(x, y);
71: }
72:
73: long double Port::fmodl(long double x, long double y)
74: {
75: return ::fmodl(x, y);
76: }
77:
78: unsigned long long Port::strtoull(const char *p, char **pend, int base)
79: {
80: return ::strtoull(p, pend, base);
81: }
82:
83: char *Port::ull_to_string(char *buffer, ulonglong ull)
84: {
85: sprintf(buffer, "%llu", ull);
86: return buffer;
87: }
88:
89: wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
90: {
91: swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
92: return buffer;
93: }
94:
95: double Port::ull_to_double(ulonglong ull)
96: {
97: return (double) ull;
98: }
99:
100: const char *Port::list_separator()
101: {
102: // LOCALE_SLIST for Windows
103: return ",";
104: }
105:
106: const wchar_t *Port::wlist_separator()
107: {
108: // LOCALE_SLIST for Windows
109: return L",";
110: }
111:
112: char *Port::strupr(char *s)
113: {
114: return ::strupr(s);
115: }
116:
117: #endif
118:
119: #if _MSC_VER
120:
121: // Disable useless warnings about unreferenced functions
122: #pragma warning (disable : 4514)
123:
124: #include <math.h>
125: #include <float.h>
126: #include <time.h>
127: #include <errno.h>
128: #include <string.h>
129: #include <ctype.h>
130: #include <stdlib.h>
131: #include <limits> // for std::numeric_limits
132:
133: static unsigned long nanarray[2]= { 0xFFFFFFFF, 0x7FFFFFFF };
134: //static unsigned long nanarray[2] = {0,0x7FF80000 };
135: double Port::nan = (*(double *)nanarray);
136:
137: //static unsigned long infinityarray[2] = {0,0x7FF00000 };
138: static double zero = 0;
139: double Port::infinity = 1 / zero;
140:
141: double Port::dbl_max = DBL_MAX;
142: double Port::dbl_min = DBL_MIN;
143: long double Port::ldbl_max = LDBL_MAX;
144:
145: struct PortInitializer
146: {
147: PortInitializer();
148: };
149:
150: static PortInitializer portinitializer;
151:
152: PortInitializer::PortInitializer()
153: {
154: Port::infinity = std::numeric_limits<long double>::infinity();
155: }
156:
157: int Port::isNan(double r)
158: {
159: return ::_isnan(r);
160: }
161:
162: int Port::isNan(long double r)
163: {
164: return ::_isnan(r);
165: }
166:
167: int Port::isSignallingNan(double r)
168: {
169: /* A signalling NaN is a NaN with 0 as the most significant bit of
170: * its significand, which is bit 51 of 0..63 for 64 bit doubles.
171: */
172: return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
173: }
174:
175: int Port::isSignallingNan(long double r)
176: {
177: /* MSVC doesn't have 80 bit long doubles
178: */
179: return isSignallingNan((double) r);
180: }
181:
182: int Port::isFinite(double r)
183: {
184: return ::_finite(r);
185: }
186:
187: int Port::isInfinity(double r)
188: {
189: return (::_fpclass(r) & (_FPCLASS_NINF | _FPCLASS_PINF));
190: }
191:
192: int Port::Signbit(double r)
193: {
194: return (long)(((long *)&(r))[1] & 0x80000000);
195: }
196:
197: double Port::floor(double d)
198: {
199: return ::floor(d);
200: }
201:
202: double Port::pow(double x, double y)
203: {
204: if (y == 0)
205: return 1; // even if x is NAN
206: return ::pow(x, y);
207: }
208:
209: long double Port::fmodl(long double x, long double y)
210: {
211: return ::fmodl(x, y);
212: }
213:
214: unsigned _int64 Port::strtoull(const char *p, char **pend, int base)
215: {
216: unsigned _int64 number = 0;
217: int c;
218: int error;
219: #define ULLONG_MAX ((unsigned _int64)~0I64)
warning C4005: 'ULLONG_MAX' : macro redefinition
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\limits.h(48) : see previous definition of 'ULLONG_MAX'
220:
221: while (isspace(*p)) /* skip leading white space */
warning C6328: 'const char' passed as parameter '1' when 'unsigned char' is required in call to 'isspace'
222: p++;
223: if (*p == '+')
224: p++;
225: switch (base)
226: { case 0:
227: base = 10; /* assume decimal base */
228: if (*p == '0')
229: { base = 8; /* could be octal */
230: p++;
231: switch (*p)
232: { case 'x':
233: case 'X':
234: base = 16; /* hex */
235: p++;
236: break;
237: #if BINARY
238: case 'b':
239: case 'B':
240: base = 2; /* binary */
241: p++;
242: break;
243: #endif
244: }
245: }
246: break;
247: case 16: /* skip over '0x' and '0X' */
248: if (*p == '0' && (p[1] == 'x' || p[1] == 'X'))
249: p += 2;
250: break;
251: #if BINARY
252: case 2: /* skip over '0b' and '0B' */
253: if (*p == '0' && (p[1] == 'b' || p[1] == 'B'))
254: p += 2;
255: break;
256: #endif
257: }
258: error = 0;
259: for (;;)
260: { c = *p;
261: if (isdigit(c))
262: c -= '0';
263: else if (isalpha(c))
264: c = (c & ~0x20) - ('A' - 10);
265: else /* unrecognized character */
266: break;
267: if (c >= base) /* not in number base */
268: break;
269: if ((ULLONG_MAX - c) / base < number)
270: error = 1;
271: number = number * base + c;
272: p++;
273: }
274: if (pend)
275: *pend = (char *)p;
276: if (error)
277: { number = ULLONG_MAX;
278: errno = ERANGE;
279: }
280: return number;
281: }
282:
283: char *Port::ull_to_string(char *buffer, ulonglong ull)
284: {
285: _ui64toa(ull, buffer, 10);
warning C4996: '_ui64toa': This function or variable may be unsafe. Consider using _ui64toa_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdlib.h(455) : see declaration of '_ui64toa'
286: return buffer;
287: }
288:
289: wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
290: {
291: _ui64tow(ull, buffer, 10);
warning C4996: '_ui64tow': This function or variable may be unsafe. Consider using _ui64tow_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\wchar.h(907) : see declaration of '_ui64tow'
292: return buffer;
293: }
294:
295: double Port::ull_to_double(ulonglong ull)
296: { double d;
297:
298: if ((__int64) ull < 0)
299: {
300: // MSVC doesn't implement the conversion
301: d = (double) (__int64)(ull - 0x8000000000000000i64);
302: d += (double)(signed __int64)(0x7FFFFFFFFFFFFFFFi64) + 1.0;
303: }
304: else
305: d = (double)(__int64)ull;
306: return d;
307: }
308:
309: const char *Port::list_separator()
310: {
311: // LOCALE_SLIST for Windows
312: return ",";
313: }
314:
315: const wchar_t *Port::wlist_separator()
316: {
317: // LOCALE_SLIST for Windows
318: return L",";
319: }
320:
321: char *Port::strupr(char *s)
322: {
323: return ::strupr(s);
warning C4996: 'strupr': The POSIX name for this item is deprecated. Instead, use the ISO C++ conformant name: _strupr. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\string.h(252) : see declaration of 'strupr'
324: }
325:
326: #endif
327:
328: #if linux || __APPLE__ || __FreeBSD__ || __OpenBSD__
329:
330: #include <math.h>
331: #if linux
332: #include <bits/nan.h>
333: #include <bits/mathdef.h>
334: #endif
335: #if __FreeBSD__ && __i386__
336: #include <ieeefp.h>
337: #endif
338: #include <time.h>
339: #include <sys/time.h>
340: #include <unistd.h>
341: #include <stdio.h>
342: #include <stdlib.h>
343: #include <ctype.h>
344: #include <float.h>
345: static char __file__[] = __FILE__; /* for tassert.h */
346: #include "tassert.h"
347:
348: static double zero = 0;
349: double Port::nan = NAN;
350: double Port::infinity = 1 / zero;
351: double Port::dbl_max = 1.7976931348623157e308;
352: double Port::dbl_min = 5e-324;
353: long double Port::ldbl_max = LDBL_MAX;
354:
355: struct PortInitializer
356: {
357: PortInitializer();
358: };
359:
360: static PortInitializer portinitializer;
361:
362: PortInitializer::PortInitializer()
363: {
364: // gcc nan's have the sign bit set by default, so turn it off
365: // Need the volatile to prevent gcc from doing incorrect
366: // constant folding.
367: volatile long double foo;
368: foo = NAN;
369: if (signbit(foo)) // signbit sometimes, not always, set
370: foo = -foo; // turn off sign bit
371: Port::nan = foo;
372:
373: #if __FreeBSD__ && __i386__
374: // LDBL_MAX comes out as infinity. Fix.
375: static unsigned char x[sizeof(long double)] =
376: { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F };
377: Port::ldbl_max = *(long double *)&x[0];
378: // FreeBSD defaults to double precision. Switch to extended precision.
379: fpsetprec(FP_PE);
380: #endif
381: }
382:
383: int Port::isNan(double r)
384: {
385: #if __APPLE__
386: return __inline_isnan(r);
387: #elif __OpenBSD__
388: return isnan(r);
389: #else
390: #undef isnan
391: return ::isnan(r);
392: #endif
393: }
394:
395: int Port::isNan(long double r)
396: {
397: #if __APPLE__
398: return __inline_isnan(r);
399: #elif __OpenBSD__
400: return isnan(r);
401: #else
402: #undef isnan
403: return ::isnan(r);
404: #endif
405: }
406:
407: int Port::isSignallingNan(double r)
408: {
409: /* A signalling NaN is a NaN with 0 as the most significant bit of
410: * its significand, which is bit 51 of 0..63 for 64 bit doubles.
411: */
412: return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
413: }
414:
415: int Port::isSignallingNan(long double r)
416: {
417: /* A signalling NaN is a NaN with 0 as the most significant bit of
418: * its significand, which is bit 62 of 0..79 for 80 bit reals.
419: */
420: return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
421: }
422:
423: #undef isfinite
424: int Port::isFinite(double r)
425: {
426: return ::finite(r);
427: }
428:
429: int Port::isInfinity(double r)
430: {
431: #if __APPLE__
432: return fpclassify(r) == FP_INFINITE;
433: #elif __OpenBSD__
434: return isinf(r);
435: #else
436: #undef isinf
437: return ::isinf(r);
438: #endif
439: }
440:
441: #undef signbit
442: int Port::Signbit(double r)
443: {
444: union { double d; long long ll; } u;
445: u.d = r;
446: return u.ll < 0;
447: }
448:
449: double Port::floor(double d)
450: {
451: return ::floor(d);
452: }
453:
454: double Port::pow(double x, double y)
455: {
456: return ::pow(x, y);
457: }
458:
459: long double Port::fmodl(long double x, long double y)
460: {
461: #if __FreeBSD__ || __OpenBSD__
462: return ::fmod(x, y); // hack for now, fix later
463: #else
464: return ::fmodl(x, y);
465: #endif
466: }
467:
468: unsigned long long Port::strtoull(const char *p, char **pend, int base)
469: {
470: return ::strtoull(p, pend, base);
471: }
472:
473: char *Port::ull_to_string(char *buffer, ulonglong ull)
474: {
475: sprintf(buffer, "%llu", ull);
476: return buffer;
477: }
478:
479: wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
480: {
481: #if __OpenBSD__
482: assert(0);
483: #else
484: swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
485: #endif
486: return buffer;
487: }
488:
489: double Port::ull_to_double(ulonglong ull)
490: {
491: return (double) ull;
492: }
493:
494: const char *Port::list_separator()
495: {
496: return ",";
497: }
498:
499: const wchar_t *Port::wlist_separator()
500: {
501: return L",";
502: }
503:
504: char *Port::strupr(char *s)
505: {
506: char *t = s;
507:
508: while (*s)
509: {
510: *s = toupper(*s);
511: s++;
512: }
513:
514: return t;
515: }
516:
517: #endif
518:
519: #if __sun&&__SVR4
520:
521: #define __C99FEATURES__ 1 // Needed on Solaris for NaN and more
522: #include <math.h>
523: #include <time.h>
524: #include <sys/time.h>
525: #include <unistd.h>
526: #include <stdio.h>
527: #include <stdlib.h>
528: #include <ctype.h>
529: #include <float.h>
530: #include <ieeefp.h>
531:
532: static double zero = 0;
533: double Port::nan = NAN;
534: double Port::infinity = 1 / zero;
535: double Port::dbl_max = 1.7976931348623157e308;
536: double Port::dbl_min = 5e-324;
537: long double Port::ldbl_max = LDBL_MAX;
538:
539: struct PortInitializer
540: {
541: PortInitializer();
542: };
543:
544: static PortInitializer portinitializer;
545:
546: PortInitializer::PortInitializer()
547: {
548: // gcc nan's have the sign bit set by default, so turn it off
549: // Need the volatile to prevent gcc from doing incorrect
550: // constant folding.
551: volatile long double foo;
552: foo = NAN;
553: if (signbit(foo)) // signbit sometimes, not always, set
554: foo = -foo; // turn off sign bit
555: Port::nan = foo;
556: }
557:
558: int Port::isNan(double r)
559: {
560: return isnan(r);
561: }
562:
563: int Port::isNan(long double r)
564: {
565: return isnan(r);
566: }
567:
568: int Port::isSignallingNan(double r)
569: {
570: /* A signalling NaN is a NaN with 0 as the most significant bit of
571: * its significand, which is bit 51 of 0..63 for 64 bit doubles.
572: */
573: return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
574: }
575:
576: int Port::isSignallingNan(long double r)
577: {
578: /* A signalling NaN is a NaN with 0 as the most significant bit of
579: * its significand, which is bit 62 of 0..79 for 80 bit reals.
580: */
581: return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
582: }
583:
584: #undef isfinite
585: int Port::isFinite(double r)
586: {
587: return finite(r);
588: }
589:
590: int Port::isInfinity(double r)
591: {
592: return isinf(r);
593: }
594:
595: #undef signbit
596: int Port::Signbit(double r)
597: {
598: return (long)(((long *)&r)[1] & 0x80000000);
599: }
600:
601: double Port::floor(double d)
602: {
603: return ::floor(d);
604: }
605:
606: double Port::pow(double x, double y)
607: {
608: return ::pow(x, y);
609: }
610:
611: unsigned long long Port::strtoull(const char *p, char **pend, int base)
612: {
613: return ::strtoull(p, pend, base);
614: }
615:
616: char *Port::ull_to_string(char *buffer, ulonglong ull)
617: {
618: sprintf(buffer, "%llu", ull);
619: return buffer;
620: }
621:
622: wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
623: {
624: swprintf(buffer, sizeof(ulonglong) * 3 + 1, L"%llu", ull);
625: return buffer;
626: }
627:
628: double Port::ull_to_double(ulonglong ull)
629: {
630: return (double) ull;
631: }
632:
633: const char *Port::list_separator()
634: {
635: return ",";
636: }
637:
638: const wchar_t *Port::wlist_separator()
639: {
640: return L",";
641: }
642:
643: char *Port::strupr(char *s)
644: {
645: char *t = s;
646:
647: while (*s)
648: {
649: *s = toupper(*s);
650: s++;
651: }
652:
653: return t;
654: }
655:
656: #endif
657:
658: #if IN_GCC
659:
660: #include <math.h>
661: #include <bits/nan.h>
662: #include <bits/mathdef.h>
663: #include <time.h>
664: #include <sys/time.h>
665: #include <unistd.h>
666: #include <stdio.h>
667: #include <stdlib.h>
668: #include <ctype.h>
669:
670: static double zero = 0;
671: double Port::nan = NAN;
672: double Port::infinity = 1 / zero;
673: double Port::dbl_max = 1.7976931348623157e308;
674: double Port::dbl_min = 5e-324;
675: long double Port::ldbl_max = LDBL_MAX;
676:
677: #include "d-gcc-real.h"
678: extern "C" bool real_isnan (const real_t *);
679:
680: struct PortInitializer
681: {
682: PortInitializer();
683: };
684:
685: static PortInitializer portinitializer;
686:
687: PortInitializer::PortInitializer()
688: {
689: Port::infinity = real_t::getinfinity();
690: Port::nan = real_t::getnan(real_t::LongDouble);
691: }
692:
693: #undef isnan
694: int Port::isNan(double r)
695: {
696: #if __APPLE__
697: return __inline_isnan(r);
698: #else
699: return ::isnan(r);
700: #endif
701: }
702:
703: int Port::isNan(long double r)
704: {
705: return real_isnan(&r);
706: }
707:
708: int Port::isSignallingNan(double r)
709: {
710: /* A signalling NaN is a NaN with 0 as the most significant bit of
711: * its significand, which is bit 51 of 0..63 for 64 bit doubles.
712: */
713: return isNan(r) && !((((unsigned char*)&r)[6]) & 8);
714: }
715:
716: int Port::isSignallingNan(long double r)
717: {
718: /* A signalling NaN is a NaN with 0 as the most significant bit of
719: * its significand, which is bit 62 of 0..79 for 80 bit reals.
720: */
721: return isNan(r) && !((((unsigned char*)&r)[7]) & 0x40);
722: }
723:
724: #undef isfinite
725: int Port::isFinite(double r)
726: {
727: return ::finite(r);
728: }
729:
730: #undef isinf
731: int Port::isInfinity(double r)
732: {
733: return ::isinf(r);
734: }
735:
736: #undef signbit
737: int Port::Signbit(double r)
738: {
739: return (long)(((long *)&r)[1] & 0x80000000);
740: }
741:
742: double Port::floor(double d)
743: {
744: return ::floor(d);
745: }
746:
747: double Port::pow(double x, double y)
748: {
749: return ::pow(x, y);
750: }
751:
752: unsigned long long Port::strtoull(const char *p, char **pend, int base)
753: {
754: return ::strtoull(p, pend, base);
755: }
756:
757: char *Port::ull_to_string(char *buffer, ulonglong ull)
758: {
759: sprintf(buffer, "%llu", ull);
760: return buffer;
761: }
762:
763: wchar_t *Port::ull_to_string(wchar_t *buffer, ulonglong ull)
764: {
765: swprintf(buffer, L"%llu", ull);
766: return buffer;
767: }
768:
769: double Port::ull_to_double(ulonglong ull)
770: {
771: return (double) ull;
772: }
773:
774: const char *Port::list_separator()
775: {
776: return ",";
777: }
778:
779: const wchar_t *Port::wlist_separator()
780: {
781: return L",";
782: }
783:
784: char *Port::strupr(char *s)
785: {
786: char *t = s;
787:
788: while (*s)
789: {
790: *s = toupper(*s);
791: s++;
792: }
793:
794: return t;
795: }
796:
797: #endif
798:
799: