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: