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