| /* 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; |
| } |