1 /* 2 * Copyright (C) 2015-2017, by Laszlo Szeremi under the Boost license. 3 * 4 * Pixel Perfect Engine, AdvancedBitArray module 5 */ 6 7 module PixelPerfectEngine.system.advBitArray; 8 import std.stdio; 9 10 public class AdvancedBitArray{ 11 private static const ubyte[8] maskData = [0b11111110,0b11111101,0b11111011,0b11110111,0b11101111,0b11011111,0b10111111,0b01111111]; 12 protected void[] rawData; 13 protected int length; 14 15 16 this(int length){ 17 setLength(length); 18 19 } 20 this(void[] data, int l){ 21 rawData = data; 22 rawData.length += 4; 23 if(rawData.length % 4){ 24 rawData.length += 4 - (rawData.length % 4); 25 } 26 length = l; 27 } 28 //this(bool[] data){} 29 30 public int getLenght(){ 31 return length; 32 } 33 34 public void setLength(int l){ 35 //test if resizing needed 36 if(length == l) return; 37 else if(length < l){ 38 if((l + 32) / 8 > rawData.length){ 39 rawData.length = (l + 32 + (32 - l%32)) / 8; 40 } 41 }else{ 42 for(int i = l ; i < length ; i++){ 43 this[i] = false; 44 } 45 rawData.length = (l + 32 + (32 - l%32)) / 8; 46 } 47 this.length = l; 48 } 49 bool opEquals()(auto ref const AdvancedBitArray o) { 50 for(int i ; i < rawData.length ; i += 4){ 51 if(cast(uint)rawData[i] != cast(uint)o.rawData[i]) return false; 52 } 53 return true; 54 } 55 AdvancedBitArray opBinary(string op)(int rhs){ 56 static if(op == ">>"){ 57 int byteShift = rhs / 8, bitShift = rhs % 8; 58 AdvancedBitArray result = new AdvancedBitArray(this.length); 59 //result.length = rawData.length; 60 if(bitShift == 0){ 61 for(int i ; i < rawData.length - byteShift ; i+=4){ 62 *cast(uint*)(result.rawData.ptr + i + byteShift) = *cast(uint*)(rawData.ptr + i); 63 } 64 }else{ 65 for(int i ; i < rawData.length - byteShift ; i+=4){ 66 uint dA = *cast(uint*)(rawData.ptr + i), dB = i == 0 ? 0 : *cast(uint*)(rawData.ptr + i - 1); 67 dA >>= bitShift; 68 dB <<= (32-bitShift); 69 *cast(uint*)(result.rawData.ptr + i + byteShift) = dA || dB; 70 } 71 } 72 return result; 73 }else static if(op == "<<"){ 74 int byteShift = rhs / 8, bitShift = rhs % 8; 75 AdvancedBitArray result = new AdvancedBitArray(this.length); 76 //result.length = rawData.length; 77 if(bitShift == 0){ 78 for(int i ; i < rawData.length - byteShift ; i+=4){ 79 *cast(uint*)(result.rawData.ptr + i) = *cast(uint*)(rawData.ptr + i + byteShift); 80 } 81 }else{ 82 for(int i ; i < rawData.length - byteShift ; i+=4){ 83 uint dA = *cast(uint*)(rawData.ptr + i + byteShift), dB = *cast(uint*)(rawData.ptr + i + byteShift + 1); 84 dA<<=bitShift; 85 dB>>=(32-bitShift); 86 *cast(uint*)(result.rawData.ptr + i + byteShift) = dA || dB; 87 } 88 } 89 return result; 90 }else static assert(0, "Operator "~op~" not implemented"); 91 } 92 AdvancedBitArray opBinary(string op)(AdvancedBitArray rhs){ 93 static if(op == "&"){ 94 AdvancedBitArray result = new AdvancedBitArray(length); 95 for(int i ; i < rawData.length ; i+=4){ 96 *cast(uint*)(result.rawData.ptr + i) = *cast(uint*)(rawData.ptr + i) & *cast(uint*)(rhs.rawData.ptr + i); 97 } 98 return result; 99 }else static if(op == "|"){ 100 AdvancedBitArray result = new AdvancedBitArray(length); 101 for(int i ; i < rawData.length ; i+=4){ 102 *cast(uint*)(result.rawData.ptr + i) = *cast(uint*)(rawData.ptr + i) | *cast(uint*)(rhs.rawData.ptr + i); 103 } 104 return result; 105 }else static if(op == "^"){ 106 AdvancedBitArray result = new AdvancedBitArray(length); 107 for(int i ; i < rawData.length ; i+=4){ 108 *cast(uint*)(result.rawData.ptr + i) = *cast(uint*)(rawData.ptr + i) ^ *cast(uint*)(rhs.rawData.ptr + i); 109 } 110 return result; 111 }else static assert(0, "Operator "~op~" not implemented"); 112 } 113 114 public string toString(){ 115 string result = "["; 116 for(int i ; i < length ; i++){ 117 if(this[i]){ 118 result ~= "1"; 119 }else{ 120 result ~= "0"; 121 } 122 } 123 result ~= "]"; 124 return result; 125 } 126 127 ref AdvancedBitArray opOPAssign(string op)(AdvancedBitArray rhs){ 128 static if(op == "&"){ 129 for(int i ; i < rawData.length ; i+=4){ 130 cast(uint)rawData[i] &= cast(uint)rhs.rawData[i]; 131 } 132 }else static if(op == "|"){ 133 for(int i ; i < rawData.length ; i+=4){ 134 cast(uint)rawData[i] |= cast(uint)rhs.rawData[i]; 135 } 136 }else static if(op == "^"){ 137 for(int i ; i < rawData.length ; i+=4){ 138 cast(uint)rawData[i] ^= cast(uint)rhs.rawData[i]; 139 } 140 }else static if(op == "~"){ 141 /*int oldlength = length; 142 this.setLength(length+rhs.length);*/ 143 if(length%8 == 0){ 144 rawData.length=length/8; 145 rawData ~= rhs.rawData; 146 this.setLength(length+rhs.length); 147 }else{ 148 149 } 150 }else static assert(0, "Operator "~op~" not implemented"); 151 } 152 153 ref AdvancedBitArray opOPAssign(string op)(bool rhs){ 154 static if(op == "~"){ 155 this[length] = rhs; 156 length++; 157 if(length % 128 == 0){ 158 rawData.length += 16; 159 } 160 }else static assert(0, "Operator "~op~" not implemented"); 161 } 162 163 bool opIndexAssign(bool value, size_t i){ 164 int bytepos = i / 8, bitpos = i % 8; 165 if(value){ 166 *cast(ubyte*)(rawData.ptr + bytepos) |= 0xFF - maskData[bitpos]; 167 }else{ 168 *cast(ubyte*)(rawData.ptr + bytepos) &= maskData[bitpos]; 169 } 170 return value; 171 } 172 173 bool opIndex(size_t i){ 174 int bytepos = i / 8, bitpos = i % 8; 175 return (*cast(ubyte*)(rawData.ptr + bytepos) & (0xFF - maskData[bitpos])) != 0; 176 } 177 AdvancedBitArray opSlice(size_t i1, size_t i2){ 178 int bitShift = i1 % 8, bitShift2 = i2 % 8, byteShift = i1 / 8, byteShift2 = i2 / 8, l = i2 - i1, l2 = byteShift2 - byteShift; 179 AdvancedBitArray result = new AdvancedBitArray(l); 180 if(bitShift == 0){ 181 for(int i ; i < l2 ; i+=4){ 182 *cast(uint*)(result.rawData.ptr + i) = *cast(uint*)(rawData.ptr + i + byteShift); 183 } 184 if(l % 32 == 0){ 185 return result; 186 } 187 }else{ 188 for(int i ; i < l2 ; i+=4){ 189 *cast(uint*)(result.rawData.ptr + i) = *cast(uint*)(rawData.ptr + i + byteShift); 190 } 191 } 192 return result; 193 } 194 public bool test(int from, int length, AdvancedBitArray target, int tfrom){ 195 int bitShiftA = from%8, bitShiftB = tfrom%8, bitlength = length%8, bitlength2 = length%32, byteShiftA = from/8, byteShiftB = tfrom/8, wordlength = length / 8; 196 int i = -3; 197 if(bitShiftA && bitShiftB){ 198 for( ; i < wordlength - 7 ; i+=4){ 199 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i))<<bitShiftA | (*cast(uint*)(rawData.ptr + (byteShiftA)+1+i))>>(32-bitShiftA), 200 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i))<<bitShiftB | (*cast(uint*)(target.rawData.ptr + (byteShiftB)+1+i))>>(32-bitShiftB); 201 if((a & b)){ 202 return true; 203 } 204 } 205 if(i < wordlength - 3 || bitlength){ 206 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i))<<bitShiftA | (*cast(uint*)(rawData.ptr + (byteShiftA)+1+i))>>(32-bitShiftA), 207 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i))<<bitShiftB | (*cast(uint*)(target.rawData.ptr + (byteShiftB)+1+i))>>(32-bitShiftB); 208 a >>= 32 - bitlength2; 209 b >>= 32 - bitlength2; 210 if((a & b)){ 211 return true; 212 } 213 } 214 }else if(bitShiftB){ 215 for( ; i < wordlength - 7 ; i+=4){ 216 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i)<<bitShiftA) , 217 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i))<<bitShiftB | (*cast(uint*)(target.rawData.ptr + (byteShiftB)+1+i))>>(32-bitShiftB); 218 if(!(a & b)){ 219 return true; 220 } 221 } 222 if(i < wordlength - 3 || bitlength){ 223 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i)<<bitShiftA) , 224 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i))<<bitShiftB | (*cast(uint*)(target.rawData.ptr + (byteShiftB)+1+i))>>(32-bitShiftB); 225 a >>= 32 - bitlength2; 226 b >>= 32 - bitlength2; 227 if((a & b)){ 228 return true; 229 } 230 } 231 }else if(bitShiftA){ 232 for( ; i < wordlength - 7 ; i+=4){ 233 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i))<<bitShiftA | (*cast(uint*)(rawData.ptr + (byteShiftA)+1+i))>>(32-bitShiftA), 234 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i)<<bitShiftB) ; 235 if((a & b)){ 236 return true; 237 } 238 } 239 if(i < wordlength -3 || bitlength){ 240 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i))<<bitShiftA | (*cast(uint*)(rawData.ptr + (byteShiftA)+1+i))>>(32-bitShiftA), 241 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i)) ; 242 a >>= 32 - bitlength2; 243 b >>= 32 - bitlength2; 244 if((a & b)){ 245 return true; 246 } 247 } 248 }else{ 249 for( ; i < wordlength - 7 ; i+=4){ 250 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i)) , 251 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i)) ; 252 if((a & b)){ 253 return true; 254 } 255 } 256 if(i < wordlength -3 || bitlength){ 257 uint a = (*cast(uint*)(rawData.ptr + (byteShiftA)+i)) , 258 b = (*cast(uint*)(target.rawData.ptr + (byteShiftB)+i)) ; 259 a >>= 32 - bitlength2; 260 b >>= 32 - bitlength2; 261 if((a & b)){ 262 return true; 263 } 264 } 265 } 266 return false; 267 } 268 }