1 20 package gov.nasa.jpf.util; 21 22 35 public class Md5Set 36 { 37 public static final int NULL = -1; 38 private static final int DEFAULT_INITIAL_CAPACITY = 10000; 39 40 private static final int VALUE_OFFSET = 0; 42 private static final int VALUE_SIZE = 4; 43 private static final int LEFT_OFFSET = VALUE_OFFSET + VALUE_SIZE; 44 private static final int RIGHT_OFFSET = LEFT_OFFSET + 1; 45 private static final int ELEMENT_SIZE = RIGHT_OFFSET + 1; 46 47 private static final int BYTES_PER_INT = 4; 48 49 private int size = 0; 50 private DynamicIntArray data; 51 private int root = 0; 52 53 56 public Md5Set() { 57 data = new DynamicIntArray(DEFAULT_INITIAL_CAPACITY * ELEMENT_SIZE); 58 } 59 60 63 public Md5Set(int initial_capacity) { 64 data = new DynamicIntArray(initial_capacity * ELEMENT_SIZE); 65 } 66 67 72 private int insert(int[] val, int left, int right) { 73 int position = size; 74 size += 1; 75 int offset = position * ELEMENT_SIZE + VALUE_OFFSET; 76 data.grow((position + 1) * ELEMENT_SIZE); 77 for(int i=0; i < VALUE_SIZE; ++i) { 78 data.set(offset + i, val[i]); 79 } 80 setLeft(position, left); 81 setRight(position, right); 82 setRed(position, true); 83 return position; 84 } 85 86 89 private int formInt(byte[] val, int offset) { 90 int result = 0; 91 for(int i=0; i < VALUE_SIZE; ++i) { 92 result = (result << 8) | (val[offset + i] & 255); 93 } 94 return result; 95 } 96 97 101 private int[] new_val = new int[VALUE_SIZE]; 102 103 106 private int[] convertValueToInts(byte[] val) { 107 assert val.length == VALUE_SIZE * BYTES_PER_INT; 108 for(int i=0; i < VALUE_SIZE; ++i) { 109 new_val[i] = formInt(val, i * BYTES_PER_INT); 110 } 111 return new_val; 112 } 113 114 119 private int compareValue(int[] val, int position) { 120 int offset = position * ELEMENT_SIZE + VALUE_OFFSET; 121 for(int i=0; i < VALUE_SIZE; ++i) { 122 int array_val = data.get(offset + i); 123 if (array_val > val[i]) { 124 return -1; 125 } else if (array_val < val[i]) { 126 return 1; 127 } 128 } 129 return 0; 130 } 131 132 136 private boolean isRed(int position) { 137 if (position == NULL) { 138 return false; 139 } 140 return (data.get(position * ELEMENT_SIZE + LEFT_OFFSET) & 1) == 1; 141 } 142 143 146 private void setRed(int position, boolean is_red) { 147 int offset = position * ELEMENT_SIZE + LEFT_OFFSET; 148 if (is_red) { 149 data.set(offset, data.get(offset) | 1); 150 } else { 151 data.set(offset, data.get(offset) & ~1); 152 } 153 } 154 155 158 private int getLeft(int position) { 159 return data.get(position * ELEMENT_SIZE + LEFT_OFFSET) >> 1; 160 } 161 162 165 private int getRight(int position) { 166 return data.get(position * ELEMENT_SIZE + RIGHT_OFFSET); 167 } 168 169 173 private void setLeft(int position, int left) { 174 int offset = position * ELEMENT_SIZE + LEFT_OFFSET; 175 data.set(offset, (left << 1) | (data.get(offset) & 1)); 176 } 177 178 181 private void setRight(int position, int right) { 182 data.set(position * ELEMENT_SIZE + RIGHT_OFFSET, right); 183 } 184 185 207 private boolean fixAfterInsert(int[] goal, int node, int parent, 208 int grandparent, int great_grandparent) { 209 int compare = compareValue(goal, node); 210 boolean keep_going = true; 211 212 if (compare < 0) { 215 keep_going = fixAfterInsert(goal, getLeft(node), node, parent, 216 grandparent); 217 } else if (compare > 0) { 218 keep_going = fixAfterInsert(goal, getRight(node), node, parent, 219 grandparent); 220 } 221 222 if (node == root) { 224 keep_going = false; 225 } 226 227 if (keep_going && isRed(node) && isRed(parent)) { 230 if (parent == getLeft(grandparent)) { 231 int uncle = getRight(grandparent); 232 if (isRed(uncle)) { 233 setRed(parent, false); 235 setRed(uncle, false); 236 setRed(grandparent, true); 237 keep_going = true; 238 } else { 239 if (node == getRight(parent)) { 240 int tmp = node; 243 node = parent; 244 parent = tmp; 245 if (node == getLeft(grandparent)) { 247 setLeft(grandparent, parent); 248 } else { 249 setRight(grandparent, parent); 250 } 251 setRight(node, getLeft(parent)); 252 setLeft(parent, node); 253 } 254 255 setRed(parent, false); 257 setRed(grandparent, true); 258 if (great_grandparent == NULL) { 260 root = parent; 261 } else if (getLeft(great_grandparent) == grandparent) { 262 setLeft(great_grandparent, parent); 263 } else { 264 setRight(great_grandparent, parent); 265 } 266 setLeft(grandparent, getRight(parent)); 267 setRight(parent, grandparent); 268 keep_going = false; 269 } 270 } else { 271 int uncle = getLeft(grandparent); 272 if (isRed(uncle)) { 273 setRed(parent, false); 275 setRed(uncle, false); 276 setRed(grandparent, true); 277 keep_going = true; 278 } else { 279 if (node == getLeft(parent)) { 280 int tmp = node; 283 node = parent; 284 parent = tmp; 285 if (node == getLeft(grandparent)) { 287 setLeft(grandparent, parent); 288 } else { 289 setRight(grandparent, parent); 290 } 291 setLeft(node, getRight(parent)); 292 setRight(parent, node); 293 } 294 setRed(parent, false); 296 setRed(grandparent, true); 297 if (great_grandparent == NULL) { 299 root = parent; 300 } else if (getRight(great_grandparent) == grandparent) { 301 setRight(great_grandparent, parent); 302 } else { 303 setLeft(great_grandparent, parent); 304 } 305 setRight(grandparent, getLeft(parent)); 306 setLeft(parent, grandparent); 307 keep_going = false; 308 } 309 } 310 } 311 return keep_going; 312 } 313 314 319 public boolean add(byte[] val) { 320 int[] int_val = convertValueToInts(val); 321 if (size == 0) { 322 insert(int_val, NULL, NULL); 323 setRed(root, false); 324 return true; 325 } 326 int current = root; 327 int prev = NULL; 328 boolean on_left = true; 329 while (current != NULL) { 330 int compare = compareValue(int_val, current); 331 if (compare == 0) { 332 return false; 333 } 334 prev = current; 335 if (compare < 0) { 336 current = getLeft(current); 337 on_left = true; 338 } else { 339 current = getRight(current); 340 on_left = false; 341 } 342 } 343 int position = insert(int_val, NULL, NULL); 344 if (on_left) { 345 setLeft(prev, position); 346 } else { 347 setRight(prev, position); 348 } 349 fixAfterInsert(int_val, root, NULL, NULL, NULL); 350 setRed(root, false); 351 return true; 352 } 353 354 public int getId(byte[] val) { 355 if (size == 0) { 356 return NULL; 357 } 358 int[] int_val = convertValueToInts(val); 359 360 if (compareValue(int_val, size - 1) == 0) { 363 return size - 1; 364 } 365 366 int current = root; 368 while (current != NULL) { 369 int compare = compareValue(int_val, current); 370 if (compare < 0) { 371 current = getLeft(current); 372 } else if (compare > 0) { 373 current = getRight(current); 374 } else { 375 return current; 376 } 377 } 378 return NULL; 379 } 380 381 384 public int size() { 385 return size; 386 } 387 388 391 private int check_count = 0; 392 393 405 private int checkSubtree(int node) { 406 if (node == NULL) { 407 return 1; 408 } 409 check_count += 1; 410 boolean is_red = isRed(node); 411 int left = getLeft(node); 412 int right = getRight(node); 413 if (is_red) { 414 assert !isRed(left) : "Left node of " + node + " is " + left + 415 " and both are red."; 416 assert !isRed(right) : "Right node of " + node + " is " + right + 417 " and both are red."; 418 } 419 int left_depth = checkSubtree(left); 420 int right_depth = checkSubtree(right); 421 assert left_depth == right_depth: "Lopsided tree at node " + node + 422 " with depths " + left_depth + " and " + right_depth; 423 if (is_red) { 424 return left_depth; 425 } else { 426 return left_depth + 1; 427 } 428 } 429 430 434 private void checkTree() { 435 check_count = 0; 436 checkSubtree(root); 437 assert check_count == size : "Traverse count " + check_count + 438 " disagrees with size " + size; 439 } 440 441 445 private static void buildTestData(byte[] data, String val) { 446 int val_len = val.length(); 447 for(int i = 0; i < 16; i++) { 448 if (i < val_len) { 449 data[i] = (byte) val.charAt(i); 450 } else { 451 data[i] = 0; 452 } 453 } 454 } 455 456 461 public static void main(String [] arg) { 462 Md5Set my_set = new Md5Set(2); 463 byte[] bytes = new byte[16]; 464 for(int i = 0; i < arg.length ; ++i) { 465 buildTestData(bytes, arg[i]); 466 System.out.println("add(" + arg[i] + ")= " + my_set.add(bytes)); 467 my_set.checkTree(); 468 } 469 System.out.println("size = " + my_set.size()); 470 for(int i = 0; i < arg.length ; ++i) { 471 buildTestData(bytes, arg[i]); 472 int id = my_set.getId(bytes); 473 assert id != -1 : "Can not find element " + arg[i]; 474 System.out.println("getId(" + arg[i] + ")= " + id); 475 } 476 } 477 } 478 479 | Popular Tags |