mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 05:00:16 +03:00
156 lines
3.4 KiB
D
156 lines
3.4 KiB
D
/* 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;
|
|
}
|