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 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/* PERMUTE_ARGS: -O
* https://issues.dlang.org/show_bug.cgi?id=19813
*/
struct BitArray
{
import core.bitop : btc, bts, btr, bsf, bt;
size_t _len;
size_t* _ptr;
enum bitsPerSizeT = size_t.sizeof * 8;
static size_t lenToDim(size_t len) @nogc pure nothrow @safe
{
return (len + (bitsPerSizeT-1)) / bitsPerSizeT;
}
this(in bool[] ba) nothrow pure
{
length = ba.length;
foreach (i, b; ba)
{
if (b)
bts(_ptr, i);
else
btr(_ptr, i);
}
}
@property size_t length(size_t newlen) pure nothrow @system
{
if (newlen != _len)
{
size_t olddim = lenToDim(_len);
immutable newdim = lenToDim(newlen);
if (newdim != olddim)
{
// Create a fake array so we can use D's realloc machinery
auto b = _ptr[0 .. olddim];
b.length = newdim; // realloc
_ptr = b.ptr;
}
_len = newlen;
}
return _len;
}
int opCmp(ref BitArray a2) const @nogc pure nothrow
{
const lesser = this._len < a2._len ? &this : &a2;
immutable fullWords = lesser._len / lesser.bitsPerSizeT;
immutable endBits = lesser._len % lesser.bitsPerSizeT;
auto p1 = this._ptr;
auto p2 = a2._ptr;
foreach (i; 0 .. fullWords)
{
if (p1[i] != p2[i])
{
return p1[i] & (size_t(1) << bsf(p1[i] ^ p2[i])) ? 1 : -1;
}
}
if (endBits)
{
immutable i = fullWords;
immutable diff = p1[i] ^ p2[i];
if (diff)
{
immutable index = bsf(diff);
if (index < endBits)
{
// This gets optimized into OPbtst, and was doing it incorrectly
return p1[i] & (size_t(1) << index) ? 1 : -1;
}
}
}
return -1;
}
}
void test1()
{
bool[] ba = [1,0,1,0,1];
bool[] bd = [1,0,1,1,1];
auto a = BitArray(ba);
auto d = BitArray(bd);
assert(a < d);
}
/***************************************/
// https://issues.dlang.org/show_bug.cgi?id=18748
int bt_32_imm(in uint* p)
{
enum bitnum = 1;
return ((p[bitnum >> 5] & (1 << (bitnum & 31)))) != 0;
}
void test18748()
{
version (linux)
{
import core.sys.posix.sys.mman;
import core.sys.posix.unistd;
// Allocate two pages.
immutable sz = 2 * sysconf(_SC_PAGESIZE);
auto m = mmap(null, sz, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
// Discard the higher page. It becomes unreadable.
munmap(m + sz / 2, sz / 2);
// Try looking at the last 4 bytes of the readable page.
uint* p = cast(uint*) (m + sz / 2 - uint.sizeof);
bt_32_imm(p);
munmap(m, sz / 2); // Free the readable page.
}
}
/***************************************/
// https://issues.dlang.org/show_bug.cgi?id=18749
ulong f(ulong* p, uint shift)
{
return (*p >> shift) & 1;
}
ulong g(ulong* p, ulong shift)
{
return f(p, cast(uint) shift);
}
void test18749()
{
enum shift = uint.max + 1L;
assert(cast(uint) shift == 0);
ulong s = 1;
assert(g(&s, shift));
}
/***************************************/
int main()
{
test1();
test18748();
test18749();
return 0;
}
|