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 }