1 ///
2 module mir.internal.utility;
3 
4 private alias AliasSeq(T...) = T;
5 
6 ///
7 alias Iota(size_t j) = Iota!(0, j);
8 
9 ///
10 template Iota(size_t i, size_t j)
11 {
12     static assert(i <= j, "Iota: i should be less than or equal to j");
13     static if (i == j)
14         alias Iota = AliasSeq!();
15     else
16         alias Iota = AliasSeq!(i, Iota!(i + 1, j));
17 }
18 
19 ///
20 template realType(C)
21     if (__traits(isFloating, C) || isComplex!C)
22 {
23     import std.traits: Unqual;
24     static if (isComplex!C)
25         alias realType = typeof(Unqual!C.init.re);
26     else
27         alias realType = Unqual!C;
28 }
29 
30 ///
31 template isComplex(C)
32 {
33     static if (is(C == struct) || is(C == enum))
34     {
35         static if (hasField!(C, "re") && hasField!(C, "im") && C.init.tupleof.length == 2)
36             enum isComplex = isFloatingPoint!(typeof(C.init.tupleof[0]));
37         else
38             enum isComplex = false;
39     }
40     else
41     {
42         // for backward compatability with cfloat, cdouble and creal
43         enum isComplex = __traits(isFloating, C) && !isFloatingPoint!C && !is(C : __vector(F[N]), F, size_t N);
44     }
45 }
46 
47 version(LDC)
48 version(mir_core_test)
49 unittest
50 {
51     static assert(!isComplex!(__vector(double[2])));
52 }
53 
54 ///
55 template isComplexOf(C, F)
56     if (isFloatingPoint!F)
57 {
58     static if (isComplex!C)
59         enum isComplexOf = is(typeof(C.init.re) == F);
60     else
61         enum isComplexOf = false;
62 }
63 
64 ///
65 template isFloatingPoint(C)
66 {
67     import std.traits: Unqual;
68     alias U = Unqual!C;
69     enum isFloatingPoint = is(U == double) || is(U == float) || is(U == real);
70 }
71 
72 // copy to reduce imports
73 enum bool hasField(T, string member) = __traits(compiles, (ref T aggregate) { return __traits(getMember, aggregate, member).offsetof; });