-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathinternal.d
127 lines (108 loc) · 3.07 KB
/
internal.d
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Private parts of Phobos
module stdx.allocator.internal;
import std.traits;
// Bulk of emplace unittests ends here
static if (is(typeof({ import std.typecons : Ternary; })))
{
public import std.typecons : Ternary;
}
else static if (is(typeof({ import std.experimental.allocator.common : Ternary; })))
{
public import std.experimental.allocator.common : Ternary;
}
else static assert(0, "Oops, dont know how to find Ternary");
/**
Check whether a number is an integer power of two.
Note that only positive numbers can be integer powers of two. This
function always return `false` if `x` is negative or zero.
Params:
x = the number to test
Returns:
`true` if `x` is an integer power of two.
*/
bool isPowerOf2(X)(const X x) pure @safe nothrow @nogc
if (isNumeric!X)
{
static if (isFloatingPoint!X)
{
import std.math : frexp;
int exp;
const X sig = frexp(x, exp);
return (exp != int.min) && (sig is cast(X) 0.5L);
}
else
{
static if (isSigned!X)
{
auto y = cast(typeof(x + 0))x;
return y > 0 && !(y & (y - 1));
}
else
{
auto y = cast(typeof(x + 0u))x;
return (y & -y) > (y - 1);
}
}
}
///
@safe unittest
{
import std.math : pow;
assert( isPowerOf2(1.0L));
assert( isPowerOf2(2.0L));
assert( isPowerOf2(0.5L));
assert( isPowerOf2(pow(2.0L, 96)));
assert( isPowerOf2(pow(2.0L, -77)));
assert(!isPowerOf2(-2.0L));
assert(!isPowerOf2(-0.5L));
assert(!isPowerOf2(0.0L));
assert(!isPowerOf2(4.315));
assert(!isPowerOf2(1.0L / 3.0L));
assert(!isPowerOf2(real.nan));
assert(!isPowerOf2(real.infinity));
}
///
@safe unittest
{
assert( isPowerOf2(1));
assert( isPowerOf2(2));
assert( isPowerOf2(1uL << 63));
assert(!isPowerOf2(-4));
assert(!isPowerOf2(0));
assert(!isPowerOf2(1337u));
}
@safe unittest
{
import std.meta : AliasSeq;
import std.math : pow;
immutable smallP2 = pow(2.0L, -62);
immutable bigP2 = pow(2.0L, 50);
immutable smallP7 = pow(7.0L, -35);
immutable bigP7 = pow(7.0L, 30);
foreach (X; AliasSeq!(float, double, real))
{
immutable min_sub = X.min_normal * X.epsilon;
foreach (x; [smallP2, min_sub, X.min_normal, .25L, 0.5L, 1.0L,
2.0L, 8.0L, pow(2.0L, X.max_exp - 1), bigP2])
{
assert( isPowerOf2(cast(X) x));
assert(!isPowerOf2(cast(X)-x));
}
foreach (x; [0.0L, 3 * min_sub, smallP7, 0.1L, 1337.0L, bigP7, X.max, real.nan, real.infinity])
{
assert(!isPowerOf2(cast(X) x));
assert(!isPowerOf2(cast(X)-x));
}
}
foreach (X; AliasSeq!(byte, ubyte, short, ushort, int, uint, long, ulong))
{
foreach (x; [1, 2, 4, 8, (X.max >>> 1) + 1])
{
assert( isPowerOf2(cast(X) x));
static if (isSigned!X)
assert(!isPowerOf2(cast(X)-x));
}
foreach (x; [0, 3, 5, 13, 77, X.min, X.max])
assert(!isPowerOf2(cast(X) x));
}
}