blob: 2cc1c236c10c1c01abb24d01cdcea8b4b64cffff [file] [log] [blame]
/**
* This module contains utilities for TypeInfo implementation.
*
* Copyright: Copyright Kenji Hara 2014-.
* License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
* Authors: Kenji Hara
*/
module rt.util.typeinfo;
static import core.internal.hash;
template Floating(T)
if (is(T == float) || is(T == double) || is(T == real))
{
pure nothrow @safe:
bool equals(T f1, T f2)
{
return f1 == f2;
}
int compare(T d1, T d2)
{
if (d1 != d1 || d2 != d2) // if either are NaN
{
if (d1 != d1)
{
if (d2 != d2)
return 0;
return -1;
}
return 1;
}
return (d1 == d2) ? 0 : ((d1 < d2) ? -1 : 1);
}
public alias hashOf = core.internal.hash.hashOf;
}
template Floating(T)
if (is(T == cfloat) || is(T == cdouble) || is(T == creal))
{
pure nothrow @safe:
bool equals(T f1, T f2)
{
return f1 == f2;
}
int compare(T f1, T f2)
{
int result;
if (f1.re < f2.re)
result = -1;
else if (f1.re > f2.re)
result = 1;
else if (f1.im < f2.im)
result = -1;
else if (f1.im > f2.im)
result = 1;
else
result = 0;
return result;
}
public alias hashOf = core.internal.hash.hashOf;
}
template Array(T)
if (is(T == float) || is(T == double) || is(T == real) ||
is(T == cfloat) || is(T == cdouble) || is(T == creal))
{
pure nothrow @safe:
bool equals(T[] s1, T[] s2)
{
size_t len = s1.length;
if (len != s2.length)
return false;
for (size_t u = 0; u < len; u++)
{
if (!Floating!T.equals(s1[u], s2[u]))
return false;
}
return true;
}
int compare(T[] s1, T[] s2)
{
size_t len = s1.length;
if (s2.length < len)
len = s2.length;
for (size_t u = 0; u < len; u++)
{
if (int c = Floating!T.compare(s1[u], s2[u]))
return c;
}
if (s1.length < s2.length)
return -1;
else if (s1.length > s2.length)
return 1;
return 0;
}
public alias hashOf = core.internal.hash.hashOf;
}
version (unittest)
{
alias TypeTuple(T...) = T;
}
unittest
{
// Bugzilla 13052
static struct SX(F) { F f; }
TypeInfo ti;
// real types
foreach (F; TypeTuple!(float, double, real))
(){ // workaround #2396
alias S = SX!F;
F f1 = +0.0,
f2 = -0.0;
assert(f1 == f2);
assert(f1 !is f2);
ti = typeid(F);
assert(ti.getHash(&f1) == ti.getHash(&f2));
F[] a1 = [f1, f1, f1];
F[] a2 = [f2, f2, f2];
assert(a1 == a2);
assert(a1 !is a2);
ti = typeid(F[]);
assert(ti.getHash(&a1) == ti.getHash(&a2));
F[][] aa1 = [a1, a1, a1];
F[][] aa2 = [a2, a2, a2];
assert(aa1 == aa2);
assert(aa1 !is aa2);
ti = typeid(F[][]);
assert(ti.getHash(&aa1) == ti.getHash(&aa2));
S s1 = {f1},
s2 = {f2};
assert(s1 == s2);
assert(s1 !is s2);
ti = typeid(S);
assert(ti.getHash(&s1) == ti.getHash(&s2));
S[] da1 = [S(f1), S(f1), S(f1)],
da2 = [S(f2), S(f2), S(f2)];
assert(da1 == da2);
assert(da1 !is da2);
ti = typeid(S[]);
assert(ti.getHash(&da1) == ti.getHash(&da2));
S[3] sa1 = {f1},
sa2 = {f2};
assert(sa1 == sa2);
assert(sa1[] !is sa2[]);
ti = typeid(S[3]);
assert(ti.getHash(&sa1) == ti.getHash(&sa2));
}();
// imaginary types
foreach (F; TypeTuple!(ifloat, idouble, ireal))
(){ // workaround #2396
alias S = SX!F;
F f1 = +0.0i,
f2 = -0.0i;
assert(f1 == f2);
assert(f1 !is f2);
ti = typeid(F);
assert(ti.getHash(&f1) == ti.getHash(&f2));
F[] a1 = [f1, f1, f1];
F[] a2 = [f2, f2, f2];
assert(a1 == a2);
assert(a1 !is a2);
ti = typeid(F[]);
assert(ti.getHash(&a1) == ti.getHash(&a2));
F[][] aa1 = [a1, a1, a1];
F[][] aa2 = [a2, a2, a2];
assert(aa1 == aa2);
assert(aa1 !is aa2);
ti = typeid(F[][]);
assert(ti.getHash(&aa1) == ti.getHash(&aa2));
S s1 = {f1},
s2 = {f2};
assert(s1 == s2);
assert(s1 !is s2);
ti = typeid(S);
assert(ti.getHash(&s1) == ti.getHash(&s2));
S[] da1 = [S(f1), S(f1), S(f1)],
da2 = [S(f2), S(f2), S(f2)];
assert(da1 == da2);
assert(da1 !is da2);
ti = typeid(S[]);
assert(ti.getHash(&da1) == ti.getHash(&da2));
S[3] sa1 = {f1},
sa2 = {f2};
assert(sa1 == sa2);
assert(sa1[] !is sa2[]);
ti = typeid(S[3]);
assert(ti.getHash(&sa1) == ti.getHash(&sa2));
}();
// complex types
foreach (F; TypeTuple!(cfloat, cdouble, creal))
(){ // workaround #2396
alias S = SX!F;
F[4] f = [+0.0 + 0.0i,
+0.0 - 0.0i,
-0.0 + 0.0i,
-0.0 - 0.0i];
foreach (i, f1; f) foreach (j, f2; f) if (i != j)
{
assert(f1 == 0 + 0i);
assert(f1 == f2);
assert(f1 !is f2);
ti = typeid(F);
assert(ti.getHash(&f1) == ti.getHash(&f2));
F[] a1 = [f1, f1, f1];
F[] a2 = [f2, f2, f2];
assert(a1 == a2);
assert(a1 !is a2);
ti = typeid(F[]);
assert(ti.getHash(&a1) == ti.getHash(&a2));
F[][] aa1 = [a1, a1, a1];
F[][] aa2 = [a2, a2, a2];
assert(aa1 == aa2);
assert(aa1 !is aa2);
ti = typeid(F[][]);
assert(ti.getHash(&aa1) == ti.getHash(&aa2));
S s1 = {f1},
s2 = {f2};
assert(s1 == s2);
assert(s1 !is s2);
ti = typeid(S);
assert(ti.getHash(&s1) == ti.getHash(&s2));
S[] da1 = [S(f1), S(f1), S(f1)],
da2 = [S(f2), S(f2), S(f2)];
assert(da1 == da2);
assert(da1 !is da2);
ti = typeid(S[]);
assert(ti.getHash(&da1) == ti.getHash(&da2));
S[3] sa1 = {f1},
sa2 = {f2};
assert(sa1 == sa2);
assert(sa1[] !is sa2[]);
ti = typeid(S[3]);
assert(ti.getHash(&sa1) == ti.getHash(&sa2));
}
}();
}