Daily bump.
[official-gcc.git] / libphobos / libdruntime / core / stdc / config.d
blobca833eaac33083ce8e7f871993a31d8748e2a9bd
1 /***
2 * D compatible types that correspond to various basic types in associated
3 * C and C++ compilers.
5 * Copyright: Copyright Sean Kelly 2005 - 2009.
6 * License: Distributed under the
7 * $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
8 * (See accompanying file LICENSE)
9 * Authors: Sean Kelly
10 * Source: $(DRUNTIMESRC core/stdc/_config.d)
11 * Standards: ISO/IEC 9899:1999 (E)
14 /* NOTE: This file has been patched from the original DMD distribution to
15 * work with the GDC compiler.
17 module core.stdc.config;
19 version (StdDdoc)
21 private
23 version (Posix)
24 enum isPosix = true;
25 else
26 enum isPosix = false;
27 static if (isPosix && (void*).sizeof > int.sizeof)
29 alias ddoc_long = long;
30 alias ddoc_ulong = ulong;
32 else
34 alias ddoc_long = int;
35 alias ddoc_ulong = uint;
37 struct ddoc_complex(T) { T re; T im; }
40 /***
41 * Used for a signed integer type that corresponds in size to the associated
42 * C compiler's `long` type.
44 alias c_long = ddoc_long;
46 /***
47 * Used for an unsigned integer type that corresponds in size to the associated
48 * C compiler's `unsigned long` type.
50 alias c_ulong = ddoc_ulong;
52 /***
53 * Used for a signed integer type that corresponds in size and mangling to the associated
54 * C++ compiler's `long` type.
56 alias cpp_long = c_long;
58 /***
59 * Used for an unsigned integer type that corresponds in size and mangling to the associated
60 * C++ compiler's `unsigned long` type.
62 alias cpp_ulong = c_ulong;
64 /***
65 * Used for a signed integer type that corresponds in size and mangling to the associated
66 * C++ compiler's `long long` type.
68 alias cpp_longlong = long;
70 /***
71 * Used for an unsigned integer type that corresponds in size and mangling to the associated
72 * C++ compiler's `unsigned long long` type.
74 alias cpp_ulonglong = ulong;
76 /***
77 * Used for a floating point type that corresponds in size and mangling to the associated
78 * C++ compiler's `long double` type.
80 alias c_long_double = real;
82 /***
83 * Used for an unsigned integer type that corresponds in size and mangling to the associated
84 * C++ compiler's `size_t` type.
86 alias cpp_size_t = size_t;
88 /***
89 * Used for a signed integer type that corresponds in size and mangling to the associated
90 * C++ compiler's `ptrdiff_t` type.
92 alias cpp_ptrdiff_t = ptrdiff_t;
94 /***
95 * Used for a complex floating point type that corresponds in size and ABI to the associated
96 * C compiler's `_Complex float` type.
98 alias c_complex_float = ddoc_complex!float;
100 /***
101 * Used for a complex floating point type that corresponds in size and ABI to the associated
102 * C compiler's `_Complex double` type.
104 alias c_complex_double = ddoc_complex!double;
106 /***
107 * Used for a complex floating point type that corresponds in size and ABI to the associated
108 * C compiler's `_Complex long double` type.
110 alias c_complex_real = ddoc_complex!real;
112 else
115 version (OSX)
116 version = Darwin;
117 else version (iOS)
118 version = Darwin;
119 else version (TVOS)
120 version = Darwin;
121 else version (WatchOS)
122 version = Darwin;
124 version (GNU)
126 import gcc.builtins;
128 alias __builtin_clong c_long;
129 alias __builtin_culong c_ulong;
131 enum __c_long : __builtin_clong;
132 enum __c_ulong : __builtin_culong;
134 alias __c_long cpp_long;
135 alias __c_ulong cpp_ulong;
137 enum __c_longlong : __builtin_clonglong;
138 enum __c_ulonglong : __builtin_culonglong;
140 alias __c_longlong cpp_longlong;
141 alias __c_ulonglong cpp_ulonglong;
143 else version (Windows)
145 enum __c_long : int;
146 enum __c_ulong : uint;
148 alias int c_long;
149 alias uint c_ulong;
151 alias __c_long cpp_long;
152 alias __c_ulong cpp_ulong;
154 alias long cpp_longlong;
155 alias ulong cpp_ulonglong;
157 else version (Posix)
159 static if ( (void*).sizeof > int.sizeof )
161 enum __c_longlong : long;
162 enum __c_ulonglong : ulong;
164 alias long c_long;
165 alias ulong c_ulong;
167 alias long cpp_long;
168 alias ulong cpp_ulong;
170 alias __c_longlong cpp_longlong;
171 alias __c_ulonglong cpp_ulonglong;
173 else
175 enum __c_long : int;
176 enum __c_ulong : uint;
178 alias int c_long;
179 alias uint c_ulong;
181 alias __c_long cpp_long;
182 alias __c_ulong cpp_ulong;
184 alias long cpp_longlong;
185 alias ulong cpp_ulonglong;
188 else version (WASI)
190 static if ( (void*).sizeof > int.sizeof )
192 enum __c_longlong : long;
193 enum __c_ulonglong : ulong;
195 alias long c_long;
196 alias ulong c_ulong;
198 alias long cpp_long;
199 alias ulong cpp_ulong;
201 alias __c_longlong cpp_longlong;
202 alias __c_ulonglong cpp_ulonglong;
204 else
206 enum __c_long : int;
207 enum __c_ulong : uint;
209 alias int c_long;
210 alias uint c_ulong;
212 alias __c_long cpp_long;
213 alias __c_ulong cpp_ulong;
215 alias long cpp_longlong;
216 alias ulong cpp_ulonglong;
220 version (GNU)
221 alias c_long_double = real;
222 else version (LDC)
223 alias c_long_double = real; // 64-bit real for MSVC targets
224 else version (SDC)
226 version (X86)
227 alias c_long_double = real;
228 else version (X86_64)
229 alias c_long_double = real;
231 else version (CRuntime_Microsoft)
233 /* long double is 64 bits, not 80 bits, but is mangled differently
234 * than double. To distinguish double from long double, create a wrapper to represent
235 * long double, then recognize that wrapper specially in the compiler
236 * to generate the correct name mangling and correct function call/return
237 * ABI conformance.
239 enum __c_long_double : double;
241 alias __c_long_double c_long_double;
243 else version (DigitalMars)
245 version (X86)
247 alias real c_long_double;
249 else version (X86_64)
251 version (linux)
252 alias real c_long_double;
253 else version (FreeBSD)
254 alias real c_long_double;
255 else version (OpenBSD)
256 alias real c_long_double;
257 else version (NetBSD)
258 alias real c_long_double;
259 else version (DragonFlyBSD)
260 alias real c_long_double;
261 else version (Solaris)
262 alias real c_long_double;
263 else version (Darwin)
264 alias real c_long_double;
268 static assert(is(c_long_double), "c_long_double needs to be declared for this platform/architecture.");
270 version (Darwin)
272 alias cpp_size_t = cpp_ulong;
273 version (D_LP64)
274 alias cpp_ptrdiff_t = cpp_long;
275 else
276 alias cpp_ptrdiff_t = ptrdiff_t;
278 else
280 alias cpp_size_t = size_t;
281 alias cpp_ptrdiff_t = ptrdiff_t;
284 /** ABI layout of native complex types.
286 struct _Complex(T)
287 if (is(T == float) || is(T == double) || is(T == c_long_double))
289 T re = 0;
290 T im = 0;
292 // Construction
293 /+ https://issues.dlang.org/show_bug.cgi?id=23788 dmd codegen problem with constructors and _Complex!float
294 this(_Complex!float c) { re = c.re; im = c.im; }
295 this(_Complex!double c) { re = c.re; im = c.im; }
296 this(_Complex!c_long_double c) { re = c.re; im = c.im; }
298 this(T re, T im) { this.re = re; this.im = im; }
300 this(T re) { this.re = re; this.im = 0; }
302 // Cast
303 R opCast(R)()
304 if (is(R == _Complex!float) || is(R == _Complex!double) || is(R == _Complex!c_long_double))
306 return R(this.re, this.im);
309 // Assignment
311 ref _Complex opAssign(_Complex!float c) { re = c.re; im = c.im; return this; }
312 ref _Complex opAssign(_Complex!double c) { re = c.re; im = c.im; return this; }
313 ref _Complex opAssign(_Complex!c_long_double c) { re = c.re; im = c.im; return this; }
315 ref _Complex opAssign(T t) { re = t; im = 0; return this; }
317 // Equals
319 bool opEquals(_Complex!float c) { return re == c.re && im == c.im; }
320 bool opEquals(_Complex!double c) { return re == c.re && im == c.im; }
321 bool opEquals(_Complex!c_long_double c) { return re == c.re && im == c.im; }
323 bool opEquals(T t) { return re == t && im == 0; }
325 // Unary operators
327 // +complex
328 _Complex opUnary(string op)()
329 if (op == "+")
331 return this;
334 // -complex
335 _Complex opUnary(string op)()
336 if (op == "-")
338 return _Complex(-re, -im);
341 // BINARY OPERATORS
343 // complex op complex
344 _Complex!(CommonType!(T,R)) opBinary(string op, R)(_Complex!R z)
346 alias C = typeof(return);
347 auto w = C(this.re, this.im);
348 return w.opOpAssign!(op)(z);
351 // complex op numeric
352 _Complex!(CommonType!(T,R)) opBinary(string op, R)(R r)
353 if (is(R : c_long_double))
355 alias C = typeof(return);
356 auto w = C(this.re, this.im);
357 return w.opOpAssign!(op)(r);
360 // numeric + complex, numeric * complex
361 _Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r)
362 if ((op == "+" || op == "*") && is(R : c_long_double))
364 return opBinary!(op)(r);
367 // numeric - complex
368 _Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r)
369 if (op == "-" && is(R : c_long_double))
371 return _Complex(r - re, -im);
374 // numeric / complex
375 _Complex!(CommonType!(T, R)) opBinaryRight(string op, R)(R r)
376 if (op == "/" && is(R : c_long_double))
378 import core.math : fabs;
379 typeof(return) w = void;
380 if (fabs(re) < fabs(im))
382 immutable ratio = re/im;
383 immutable rdivd = r/(re*ratio + im);
385 w.re = rdivd*ratio;
386 w.im = -rdivd;
388 else
390 immutable ratio = im/re;
391 immutable rdivd = r/(re + im*ratio);
393 w.re = rdivd;
394 w.im = -rdivd*ratio;
397 return w;
400 // OP-ASSIGN OPERATORS
402 // complex += complex, complex -= complex
403 ref _Complex opOpAssign(string op, C)(C z)
404 if ((op == "+" || op == "-") && is(C R == _Complex!R))
406 mixin ("re "~op~"= z.re;");
407 mixin ("im "~op~"= z.im;");
408 return this;
411 // complex *= complex
412 ref _Complex opOpAssign(string op, C)(C z)
413 if (op == "*" && is(C R == _Complex!R))
415 auto temp = re*z.re - im*z.im;
416 im = im*z.re + re*z.im;
417 re = temp;
418 return this;
421 // complex /= complex
422 ref _Complex opOpAssign(string op, C)(C z)
423 if (op == "/" && is(C R == _Complex!R))
425 import core.math : fabs;
426 if (fabs(z.re) < fabs(z.im))
428 immutable ratio = z.re/z.im;
429 immutable denom = z.re*ratio + z.im;
431 immutable temp = (re*ratio + im)/denom;
432 im = (im*ratio - re)/denom;
433 re = temp;
435 else
437 immutable ratio = z.im/z.re;
438 immutable denom = z.re + z.im*ratio;
440 immutable temp = (re + im*ratio)/denom;
441 im = (im - re*ratio)/denom;
442 re = temp;
444 return this;
447 // complex += numeric, complex -= numeric
448 ref _Complex opOpAssign(string op, U : T)(U a)
449 if (op == "+" || op == "-")
451 mixin ("re "~op~"= a;");
452 return this;
455 // complex *= numeric, complex /= numeric
456 ref _Complex opOpAssign(string op, U : T)(U a)
457 if (op == "*" || op == "/")
459 mixin ("re "~op~"= a;");
460 mixin ("im "~op~"= a;");
461 return this;
464 // Helper properties.
465 pragma(inline, true)
467 static @property epsilon()() { return _Complex(T.epsilon, T.epsilon); }
468 static @property infinity()() { return _Complex(T.infinity, T.infinity); }
469 static @property max()() { return _Complex(T.max, T.max); }
470 static @property min_normal()() { return _Complex(T.min_normal, T.min_normal); }
471 static @property nan()() { return _Complex(T.nan, T.nan); }
472 static @property dig()() { return T.dig; }
473 static @property mant_dig()() { return T.mant_dig; }
474 static @property max_10_exp()() { return T.max_10_exp; }
475 static @property max_exp()() { return T.max_exp; }
476 static @property min_10_exp()() { return T.min_10_exp; }
477 static @property min_exp()() { return T.min_exp; }
481 enum __c_complex_float : _Complex!float;
482 enum __c_complex_double : _Complex!double;
483 enum __c_complex_real : _Complex!c_long_double;
485 alias c_complex_float = __c_complex_float;
486 alias c_complex_double = __c_complex_double;
487 alias c_complex_real = __c_complex_real;
489 private template CommonType(T, R)
491 // Special kludge for Microsoft c_long_double
492 static if (is(T == c_long_double))
493 alias CommonType = T;
494 else static if (is(R == c_long_double))
495 alias CommonType = R;
496 else
497 alias CommonType = typeof(true ? T.init : R.init);
500 /************ unittests ****************/
502 version (unittest)
504 private:
506 alias _cfloat = _Complex!float;
507 alias _cdouble = _Complex!double;
508 alias _creal = _Complex!c_long_double;
510 T abs(T)(T t) => t < 0 ? -t : t;
513 @safe pure nothrow unittest
515 auto c1 = _cdouble(1.0, 1.0);
517 // Check unary operations.
518 auto c2 = _cdouble(0.5, 2.0);
520 assert(c2 == +c2);
522 assert((-c2).re == -(c2.re));
523 assert((-c2).im == -(c2.im));
524 assert(c2 == -(-c2));
526 // Check complex-complex operations.
527 auto cpc = c1 + c2;
528 assert(cpc.re == c1.re + c2.re);
529 assert(cpc.im == c1.im + c2.im);
531 auto cmc = c1 - c2;
532 assert(cmc.re == c1.re - c2.re);
533 assert(cmc.im == c1.im - c2.im);
535 auto ctc = c1 * c2;
536 assert(ctc == _cdouble(-1.5, 2.5));
538 auto cdc = c1 / c2;
539 assert(abs(cdc.re - 0.5882352941177) < 1e-12);
540 assert(abs(cdc.im - -0.3529411764706) < 1e-12);
542 // Check complex-real operations.
543 double a = 123.456;
545 auto cpr = c1 + a;
546 assert(cpr.re == c1.re + a);
547 assert(cpr.im == c1.im);
549 auto cmr = c1 - a;
550 assert(cmr.re == c1.re - a);
551 assert(cmr.im == c1.im);
553 auto ctr = c1 * a;
554 assert(ctr.re == c1.re*a);
555 assert(ctr.im == c1.im*a);
557 auto cdr = c1 / a;
558 assert(abs(cdr.re - 0.00810005184033) < 1e-12);
559 assert(abs(cdr.im - 0.00810005184033) < 1e-12);
561 auto rpc = a + c1;
562 assert(rpc == cpr);
564 auto rmc = a - c1;
565 assert(rmc.re == a-c1.re);
566 assert(rmc.im == -c1.im);
568 auto rtc = a * c1;
569 assert(rtc == ctr);
571 auto rdc = a / c1;
572 assert(abs(rdc.re - 61.728) < 1e-12);
573 assert(abs(rdc.im - -61.728) < 1e-12);
575 rdc = a / c2;
576 assert(abs(rdc.re - 14.5242352941) < 1e-10);
577 assert(abs(rdc.im - -58.0969411765) < 1e-10);
579 // Check operations between different complex types.
580 auto cf = _cfloat(1.0, 1.0);
581 auto cr = _creal(1.0, 1.0);
582 auto c1pcf = c1 + cf;
583 auto c1pcr = c1 + cr;
584 static assert(is(typeof(c1pcf) == _cdouble));
585 static assert(is(typeof(c1pcr) == _creal));
586 assert(c1pcf.re == c1pcr.re);
587 assert(c1pcf.im == c1pcr.im);
589 auto c1c = c1;
590 auto c2c = c2;
592 c1c /= c1;
593 assert(abs(c1c.re - 1.0) < 1e-10);
594 assert(abs(c1c.im - 0.0) < 1e-10);
596 c1c = c1;
597 c1c /= c2;
598 assert(abs(c1c.re - 0.5882352941177) < 1e-12);
599 assert(abs(c1c.im - -0.3529411764706) < 1e-12);
601 c2c /= c1;
602 assert(abs(c2c.re - 1.25) < 1e-11);
603 assert(abs(c2c.im - 0.75) < 1e-12);
605 c2c = c2;
606 c2c /= c2;
607 assert(abs(c2c.re - 1.0) < 1e-11);
608 assert(abs(c2c.im - 0.0) < 1e-12);
611 @safe pure nothrow unittest
613 // Initialization
614 _cdouble a = _cdouble(1, 0);
615 assert(a.re == 1 && a.im == 0);
616 _cdouble b = _cdouble(1.0, 0);
617 assert(b.re == 1.0 && b.im == 0);
618 // _cdouble c = _creal(1.0, 2);
619 // assert(c.re == 1.0 && c.im == 2);
622 @safe pure nothrow unittest
624 // Assignments and comparisons
625 _cdouble z;
627 z = 1;
628 assert(z == 1);
629 assert(z.re == 1.0 && z.im == 0.0);
631 z = 2.0;
632 assert(z == 2.0);
633 assert(z.re == 2.0 && z.im == 0.0);
635 z = 1.0L;
636 assert(z == 1.0L);
637 assert(z.re == 1.0 && z.im == 0.0);
639 auto w = _creal(1.0, 1.0);
640 z = w;
641 assert(z == w);
642 assert(z.re == 1.0 && z.im == 1.0);
644 auto c = _cfloat(2.0, 2.0);
645 z = c;
646 assert(z == c);
647 assert(z.re == 2.0 && z.im == 2.0);
653 // Returns the mangled name for the 64-bit time_t versions of
654 // functions affected by musl's transition to 64-bit time_t.
655 // https://musl.libc.org/time64.html
656 version (CRuntime_Musl)
658 version (CRuntime_Musl_Pre_Time64)
659 enum muslRedirTime64 = false;
660 else
662 // time_t was defined as a C long in older Musl versions.
663 enum muslRedirTime64 = (c_long.sizeof == 4);
666 else
667 enum muslRedirTime64 = false;
669 package(core) template muslRedirTime64Mangle(string name, string redirectedName)
671 static if (muslRedirTime64)
672 enum muslRedirTime64Mangle = redirectedName;
673 else
674 enum muslRedirTime64Mangle = name;