1 /* 2 ******************************************************************************* 3 * Copyright (C) 2002-2012, International Business Machines Corporation and * 4 * others. All Rights Reserved. * 5 ******************************************************************************* 6 */ 7 package org.unicode.cldr.util; 8 9 import java.util.ArrayList; 10 import java.util.Arrays; 11 import java.util.HashSet; 12 import java.util.Random; 13 import java.util.Set; 14 15 import com.ibm.icu.text.UTF16; 16 import com.ibm.icu.text.UnicodeSet; 17 18 abstract public class Pick { 19 private static boolean DEBUG = false; 20 21 // for using to get strings 22 23 static class Target { 24 private Pick pick; 25 private Random random; 26 private Quoter quoter; 27 make(Pick pick, Random random, Quoter quoter)28 public static Target make(Pick pick, Random random, Quoter quoter) { 29 Target result = new Target(); 30 result.pick = pick; 31 result.random = random; 32 result.quoter = quoter; 33 return result; 34 } 35 next()36 public String next() { 37 quoter.clear(); 38 pick.addTo(this); 39 return get(); 40 } 41 get()42 public String get() { 43 return quoter.toString(); 44 } 45 copyState(Target other)46 private void copyState(Target other) { 47 random = other.random; 48 } 49 clear()50 private void clear() { 51 quoter.clear(); 52 } 53 54 /*private int length() { 55 return quoter.length(); 56 }*/ append(int codepoint)57 private Target append(int codepoint) { 58 quoter.append(codepoint); 59 return this; 60 } 61 append(String s)62 private Target append(String s) { 63 quoter.append(s); 64 return this; 65 } 66 67 // must return value between 0 (inc) and 1 (exc) nextDouble()68 private double nextDouble() { 69 return random.nextDouble(); 70 } 71 } 72 73 // for Building 74 replace(String toReplace, Pick replacement)75 public Pick replace(String toReplace, Pick replacement) { 76 Replacer visitor = new Replacer(toReplace, replacement); 77 return visit(visitor); 78 } 79 name(String nameStr)80 public Pick name(String nameStr) { 81 name = nameStr; 82 return this; 83 } 84 makeSequence()85 static public Pick.Sequence makeSequence() { 86 return new Sequence(); 87 } 88 makeAlternation()89 static public Pick.Alternation makeAlternation() { 90 return new Alternation(); 91 } 92 /* 93 static public Pick.Sequence and(Object item) { 94 return new Sequence().and2(item); 95 } 96 static public Pick.Sequence and(Object[] items) { 97 return new Sequence().and2(items); 98 } 99 static public Pick.Alternation or(int itemWeight, Object item) { 100 return new Alternation().or2(itemWeight, item); 101 } 102 static public Pick.Alternation or(Object[] items) { 103 return new Alternation().or2(1, items); 104 } 105 static public Pick.Alternation or(int itemWeight, Object[] items) { 106 return new Alternation().or2(itemWeight, items); 107 } 108 static public Pick.Alternation or(int[] itemWeights, Object[] items) { 109 return new Alternation().or2(itemWeights, items); 110 } 111 112 static public Pick maybe(int percent, Object item) { 113 return new Repeat(0, 1, new int[]{100-percent, percent}, item); 114 //return Pick.or(1.0-percent, NOTHING).or2(percent, item); 115 } 116 static public Pick repeat(int minCount, int maxCount, int itemWeights, Object item) { 117 return new Repeat(minCount, maxCount, itemWeights, item); 118 } 119 120 static public Pick codePoint(String source) { 121 return new CodePoint(new UnicodeSet(source)); 122 } 123 */ 124 repeat(int minCount, int maxCount, int[] itemWeights, Pick item)125 static public Pick repeat(int minCount, int maxCount, int[] itemWeights, Pick item) { 126 return new Repeat(minCount, maxCount, itemWeights, item); 127 } 128 codePoint(UnicodeSet source)129 static public Pick codePoint(UnicodeSet source) { 130 return new CodePoint(source); 131 } 132 string(String source)133 static public Pick string(String source) { 134 return new Literal(source); 135 } 136 /* 137 static public Pick unquoted(String source) { 138 return new Literal(source); 139 } 140 static public Pick string(int minLength, int maxLength, Pick item) { 141 return new Morph(item, minLength, maxLength); 142 } 143 */ 144 getInternal(int depth, Set alreadySeen)145 public abstract String getInternal(int depth, Set alreadySeen); 146 // Internals 147 148 protected String name; 149 addTo(Target target)150 protected abstract void addTo(Target target); 151 match(String input, Position p)152 public abstract boolean match(String input, Position p); 153 154 public static class Sequence extends ListPick { and2(Pick item)155 public Sequence and2(Pick item) { 156 addInternal(new Pick[] { item }); // we don't care about perf 157 return this; // for chaining 158 } 159 and2(Pick[] itemArray)160 public Sequence and2(Pick[] itemArray) { 161 addInternal(itemArray); 162 return this; // for chaining 163 } 164 165 @Override addTo(Target target)166 protected void addTo(Target target) { 167 for (int i = 0; i < items.length; ++i) { 168 items[i].addTo(target); 169 } 170 } 171 172 @Override getInternal(int depth, Set alreadySeen)173 public String getInternal(int depth, Set alreadySeen) { 174 String result = checkName(name, alreadySeen); 175 if (result.startsWith("$")) return result; 176 result = indent(depth) + result + "SEQ("; 177 for (int i = 0; i < items.length; ++i) { 178 if (i != 0) result += ", "; 179 result += items[i].getInternal(depth + 1, alreadySeen); 180 } 181 result += ")"; 182 return result; 183 } 184 185 // keep private Sequence()186 private Sequence() { 187 } 188 189 @Override match(String input, Position p)190 public boolean match(String input, Position p) { 191 int originalIndex = p.index; 192 for (int i = 0; i < items.length; ++i) { 193 if (!items[i].match(input, p)) { 194 p.index = originalIndex; 195 return false; 196 } 197 } 198 return true; 199 } 200 } 201 checkName(String nameStr, Set alreadySeen)202 String checkName(String nameStr, Set alreadySeen) { 203 if (nameStr == null) return ""; 204 if (alreadySeen.contains(nameStr)) return nameStr; 205 alreadySeen.add(nameStr); 206 return "{" + nameStr + "=}"; 207 } 208 209 public static class Alternation extends ListPick { 210 private WeightedIndex weightedIndex = new WeightedIndex(0); 211 or2(Pick[] newItems)212 public Alternation or2(Pick[] newItems) { 213 return or2(1, newItems); 214 } 215 or2(int itemWeight, Pick item)216 public Alternation or2(int itemWeight, Pick item) { 217 return or2(itemWeight, new Pick[] { item }); // we don't care about perf 218 } 219 or2(int itemWeight, Pick[] newItems)220 public Alternation or2(int itemWeight, Pick[] newItems) { 221 int[] itemWeights = new int[newItems.length]; 222 Arrays.fill(itemWeights, itemWeight); 223 return or2(itemWeights, newItems); // we don't care about perf 224 } 225 or2(int[] itemWeights, Pick[] newItems)226 public Alternation or2(int[] itemWeights, Pick[] newItems) { 227 if (newItems.length != itemWeights.length) { 228 throw new ArrayIndexOutOfBoundsException( 229 "or lengths must be equal: " + newItems.length + " != " + itemWeights.length); 230 } 231 // int lastLen = this.items.length; 232 addInternal(newItems); 233 weightedIndex.add(itemWeights); 234 return this; // for chaining 235 } 236 237 @Override addTo(Target target)238 protected void addTo(Target target) { 239 items[weightedIndex.toIndex(target.nextDouble())].addTo(target); 240 } 241 242 @Override getInternal(int depth, Set alreadySeen)243 public String getInternal(int depth, Set alreadySeen) { 244 String result = checkName(name, alreadySeen); 245 if (result.startsWith("$")) return result; 246 result = indent(depth) + result + "OR("; 247 for (int i = 0; i < items.length; ++i) { 248 if (i != 0) result += ", "; 249 result += items[i].getInternal(depth + 1, alreadySeen) + "/" + weightedIndex.weights[i]; 250 } 251 return result + ")"; 252 } 253 254 // keep private Alternation()255 private Alternation() { 256 } 257 258 // take first matching option 259 @Override match(String input, Position p)260 public boolean match(String input, Position p) { 261 for (int i = 0; i < weightedIndex.weights.length; ++i) { 262 if (p.isFailure(this, i)) continue; 263 if (items[i].match(input, p)) return true; 264 p.setFailure(this, i); 265 } 266 return false; 267 } 268 } 269 indent(int depth)270 private static String indent(int depth) { 271 String result = "\r\n"; 272 for (int i = 0; i < depth; ++i) { 273 result += " "; 274 } 275 return result; 276 } 277 278 private static class Repeat extends ItemPick { 279 WeightedIndex weightedIndex; 280 int minCount = 0; 281 Repeat(int minCount, int maxCount, int[] itemWeights, Pick item)282 private Repeat(int minCount, int maxCount, int[] itemWeights, Pick item) { 283 super(item); 284 weightedIndex = new WeightedIndex(minCount).add(maxCount - minCount + 1, itemWeights); 285 } 286 287 /*private Repeat(int minCount, int maxCount, int itemWeight, Pick item) { 288 super(item); 289 weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, itemWeight); 290 }*/ 291 /* 292 private Repeat(int minCount, int maxCount, Object item) { 293 this.item = convert(item); 294 weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, 1); 295 } 296 */ 297 @Override addTo(Target target)298 protected void addTo(Target target) { 299 //int count ; 300 for (int i = weightedIndex.toIndex(target.nextDouble()); i > 0; --i) { 301 item.addTo(target); 302 } 303 } 304 305 @Override getInternal(int depth, Set alreadySeen)306 public String getInternal(int depth, Set alreadySeen) { 307 String result = checkName(name, alreadySeen); 308 if (result.startsWith("$")) return result; 309 result = indent(depth) + result + "REPEAT(" + weightedIndex 310 + "; " + item.getInternal(depth + 1, alreadySeen) 311 + ")"; 312 return result; 313 } 314 315 // match longest, e.g. up to just before a failure 316 @Override match(String input, Position p)317 public boolean match(String input, Position p) { 318 //int bestMatch = p.index; 319 int count = 0; 320 for (int i = 0; i < weightedIndex.weights.length; ++i) { 321 if (p.isFailure(this, i)) break; 322 if (!item.match(input, p)) { 323 p.setFailure(this, i); 324 break; 325 } 326 //bestMatch = p.index; 327 count++; 328 } 329 if (count >= minCount) { 330 return true; 331 } 332 // TODO fix failure 333 return false; 334 } 335 } 336 337 private static class CodePoint extends FinalPick { 338 private UnicodeSet source; 339 CodePoint(UnicodeSet source)340 private CodePoint(UnicodeSet source) { 341 this.source = source; 342 } 343 344 @Override addTo(Target target)345 protected void addTo(Target target) { 346 target.append(source.charAt(pick(target.random, 0, source.size() - 1))); 347 } 348 349 @Override match(String s, Position p)350 public boolean match(String s, Position p) { 351 int cp = UTF16.charAt(s, p.index); 352 if (source.contains(cp)) { 353 p.index += UTF16.getCharCount(cp); 354 return true; 355 } 356 p.setMax("codePoint"); 357 return false; 358 } 359 360 @Override getInternal(int depth, Set alreadySeen)361 public String getInternal(int depth, Set alreadySeen) { 362 String result = checkName(name, alreadySeen); 363 if (result.startsWith("$")) return result; 364 return source.toString(); 365 } 366 } 367 368 static class Morph extends ItemPick { Morph(Pick item)369 Morph(Pick item) { 370 super(item); 371 } 372 373 private String lastValue = null; 374 private Target addBuffer = Target.make(this, null, new Quoter.RuleQuoter()); 375 private StringBuffer mergeBuffer = new StringBuffer(); 376 377 private static final int COPY_NEW = 0, COPY_BOTH = 1, COPY_LAST = 3, SKIP = 4, 378 LEAST_SKIP = 4; 379 // give weights to the above. make sure we delete about the same as we insert 380 private static final WeightedIndex choice = new WeightedIndex(0) 381 .add(new int[] { 10, 10, 100, 10 }); 382 383 @Override addTo(Target target)384 protected void addTo(Target target) { 385 // get contents into separate buffer 386 addBuffer.copyState(target); 387 addBuffer.clear(); 388 item.addTo(addBuffer); 389 String newValue = addBuffer.get(); 390 if (DEBUG) System.out.println("Old: " + lastValue + ", New:" + newValue); 391 392 // if not first one, merge with old 393 if (lastValue != null) { 394 mergeBuffer.setLength(0); 395 int lastIndex = 0; 396 int newIndex = 0; 397 // the new length is a random value between old and new. 398 int newLenLimit = pick(target.random, lastValue.length(), newValue.length()); 399 400 while (mergeBuffer.length() < newLenLimit 401 && newIndex < newValue.length() 402 && lastIndex < lastValue.length()) { 403 int c = choice.toIndex(target.nextDouble()); 404 if (c == COPY_NEW || c == COPY_BOTH || c == SKIP) { 405 newIndex = getChar(newValue, newIndex, mergeBuffer, c < LEAST_SKIP); 406 if (mergeBuffer.length() >= newLenLimit) break; 407 } 408 if (c == COPY_LAST || c == COPY_BOTH || c == SKIP) { 409 lastIndex = getChar(lastValue, lastIndex, mergeBuffer, c < LEAST_SKIP); 410 } 411 } 412 newValue = mergeBuffer.toString(); 413 } 414 lastValue = newValue; 415 target.append(newValue); 416 if (DEBUG) System.out.println("Result: " + newValue); 417 } 418 419 @Override getInternal(int depth, Set alreadySeen)420 public String getInternal(int depth, Set alreadySeen) { 421 String result = checkName(name, alreadySeen); 422 if (result.startsWith("$")) return result; 423 return indent(depth) + result + "MORPH(" 424 + item.getInternal(depth + 1, alreadySeen) 425 + ")"; 426 } 427 428 /* (non-Javadoc) 429 * @see Pick#match(java.lang.String, Pick.Position) 430 */ 431 @Override match(String input, Position p)432 public boolean match(String input, Position p) { 433 // TODO Auto-generated method stub 434 return false; 435 } 436 } 437 438 /* Add character if we can 439 */ getChar(String newValue, int newIndex, StringBuffer mergeBuffer, boolean copy)440 static int getChar(String newValue, int newIndex, StringBuffer mergeBuffer, boolean copy) { 441 if (newIndex >= newValue.length()) return newIndex; 442 int cp = UTF16.charAt(newValue, newIndex); 443 if (copy) UTF16.append(mergeBuffer, cp); 444 return newIndex + UTF16.getCharCount(cp); 445 } 446 447 /* 448 // quoted add 449 appendQuoted(target, addBuffer.toString(), quoteBuffer); 450 // fix buffers 451 StringBuffer swapTemp = addBuffer; 452 addBuffer = source; 453 source = swapTemp; 454 } 455 } 456 */ 457 458 static class Quote extends ItemPick { Quote(Pick item)459 Quote(Pick item) { 460 super(item); 461 } 462 463 @Override addTo(Target target)464 protected void addTo(Target target) { 465 target.quoter.setQuoting(true); 466 item.addTo(target); 467 target.quoter.setQuoting(false); 468 } 469 470 @Override match(String s, Position p)471 public boolean match(String s, Position p) { 472 return false; 473 } 474 475 @Override getInternal(int depth, Set alreadySeen)476 public String getInternal(int depth, Set alreadySeen) { 477 String result = checkName(name, alreadySeen); 478 if (result.startsWith("$")) return result; 479 return indent(depth) + result + "QUOTE(" + item.getInternal(depth + 1, alreadySeen) 480 + ")"; 481 } 482 } 483 484 private static class Literal extends FinalPick { 485 @Override toString()486 public String toString() { 487 return name; 488 } 489 Literal(String source)490 private Literal(String source) { 491 this.name = source; 492 } 493 494 @Override addTo(Target target)495 protected void addTo(Target target) { 496 target.append(name); 497 } 498 499 @Override match(String input, Position p)500 public boolean match(String input, Position p) { 501 int len = name.length(); 502 if (input.regionMatches(p.index, name, 0, len)) { 503 p.index += len; 504 return true; 505 } 506 p.setMax("literal"); 507 return false; 508 } 509 510 @Override getInternal(int depth, Set alreadySeen)511 public String getInternal(int depth, Set alreadySeen) { 512 return "'" + name + "'"; 513 } 514 } 515 516 public static class Position { 517 public ArrayList failures = new ArrayList(); 518 public int index; 519 public int maxInt; 520 public String maxType; 521 setMax(String type)522 public void setMax(String type) { 523 if (index >= maxInt) { 524 maxType = type; 525 } 526 } 527 528 @Override toString()529 public String toString() { 530 return "index; " + index 531 + ", maxInt:" + maxInt 532 + ", maxType: " + maxType; 533 } 534 /*private static final Object BAD = new Object(); 535 private static final Object GOOD = new Object();*/ 536 isFailure(Pick pick, int item)537 public boolean isFailure(Pick pick, int item) { 538 ArrayList val = (ArrayList) failures.get(index); 539 if (val == null) return false; 540 Set set = (Set) val.get(item); 541 if (set == null) return false; 542 return !set.contains(pick); 543 } 544 setFailure(Pick pick, int item)545 public void setFailure(Pick pick, int item) { 546 ArrayList val = (ArrayList) failures.get(index); 547 if (val == null) { 548 val = new ArrayList(); 549 failures.set(index, val); 550 } 551 Set set = (Set) val.get(item); 552 if (set == null) { 553 set = new HashSet(); 554 val.set(item, set); 555 } 556 set.add(pick); 557 } 558 } 559 560 /* 561 public static final Pick NOTHING = new Nothing(); 562 563 564 private static class Nothing extends FinalPick { 565 protected void addTo(Target target) {} 566 protected boolean match(String input, Position p) { 567 return true; 568 } 569 public String getInternal(int depth, Set alreadySeen) { 570 return indent(depth) + "\u00F8"; 571 } 572 } 573 */ 574 575 // intermediates 576 577 abstract static class Visitor { 578 Set already = new HashSet(); 579 580 // Note: each visitor should return the Pick that will replace a (or a itself) handle(Pick a)581 abstract Pick handle(Pick a); 582 alreadyEntered(Pick item)583 boolean alreadyEntered(Pick item) { 584 boolean result = already.contains(item); 585 already.add(item); 586 return result; 587 } 588 reset()589 void reset() { 590 already.clear(); 591 } 592 } 593 visit(Visitor visitor)594 protected abstract Pick visit(Visitor visitor); 595 596 static class Replacer extends Visitor { 597 String toReplace; 598 Pick replacement; 599 Replacer(String toReplace, Pick replacement)600 Replacer(String toReplace, Pick replacement) { 601 this.toReplace = toReplace; 602 this.replacement = replacement; 603 } 604 605 @Override handle(Pick a)606 public Pick handle(Pick a) { 607 if (toReplace.equals(a.name)) { 608 a = replacement; 609 } 610 return a; 611 } 612 } 613 614 abstract private static class FinalPick extends Pick { 615 @Override visit(Visitor visitor)616 public Pick visit(Visitor visitor) { 617 return visitor.handle(this); 618 } 619 } 620 621 private abstract static class ItemPick extends Pick { 622 protected Pick item; 623 ItemPick(Pick item)624 ItemPick(Pick item) { 625 this.item = item; 626 } 627 628 @Override visit(Visitor visitor)629 public Pick visit(Visitor visitor) { 630 Pick result = visitor.handle(this); 631 if (visitor.alreadyEntered(this)) return result; 632 if (item != null) item = item.visit(visitor); 633 return result; 634 } 635 } 636 637 private abstract static class ListPick extends Pick { 638 protected Pick[] items = new Pick[0]; 639 simplify()640 Pick simplify() { 641 if (items.length > 1) return this; 642 if (items.length == 1) return items[0]; 643 return null; 644 } 645 size()646 int size() { 647 return items.length; 648 } 649 getLast()650 Pick getLast() { 651 return items[items.length - 1]; 652 } 653 setLast(Pick newOne)654 void setLast(Pick newOne) { 655 items[items.length - 1] = newOne; 656 } 657 addInternal(Pick[] objs)658 protected void addInternal(Pick[] objs) { 659 int lastLen = items.length; 660 items = realloc(items, items.length + objs.length); 661 for (int i = 0; i < objs.length; ++i) { 662 items[lastLen + i] = objs[i]; 663 } 664 } 665 666 @Override visit(Visitor visitor)667 public Pick visit(Visitor visitor) { 668 Pick result = visitor.handle(this); 669 if (visitor.alreadyEntered(this)) return result; 670 for (int i = 0; i < items.length; ++i) { 671 items[i] = items[i].visit(visitor); 672 } 673 return result; 674 } 675 } 676 677 /** 678 * Simple class to distribute a number between 0 (inclusive) and 1 (exclusive) among 679 * a number of indices, where each index is weighted. 680 * Item weights may be zero, but cannot be negative. 681 * @author Davis 682 */ 683 // As in other case, we use an array for runtime speed; don't care about buildspeed. 684 public static class WeightedIndex { 685 private int[] weights = new int[0]; 686 private int minCount = 0; 687 private double total; 688 WeightedIndex(int minCount)689 public WeightedIndex(int minCount) { 690 this.minCount = minCount; 691 } 692 add(int count, int itemWeights)693 public WeightedIndex add(int count, int itemWeights) { 694 if (count > 0) { 695 int[] newWeights = new int[count]; 696 if (itemWeights < 1) itemWeights = 1; 697 Arrays.fill(newWeights, 0, count, itemWeights); 698 add(1, newWeights); 699 } 700 return this; // for chaining 701 } 702 add(int[] newWeights)703 public WeightedIndex add(int[] newWeights) { 704 return add(newWeights.length, newWeights); 705 } 706 add(int maxCount, int[] newWeights)707 public WeightedIndex add(int maxCount, int[] newWeights) { 708 if (newWeights == null) newWeights = new int[] { 1 }; 709 int oldLen = weights.length; 710 if (maxCount < newWeights.length) maxCount = newWeights.length; 711 weights = realloc(weights, weights.length + maxCount); 712 System.arraycopy(newWeights, 0, weights, oldLen, newWeights.length); 713 int lastWeight = weights[oldLen + newWeights.length - 1]; 714 for (int i = oldLen + newWeights.length; i < maxCount; ++i) { 715 weights[i] = lastWeight; 716 } 717 total = 0; 718 for (int i = 0; i < weights.length; ++i) { 719 if (weights[i] < 0) { 720 throw new RuntimeException("only positive weights: " + i); 721 } 722 total += weights[i]; 723 } 724 return this; // for chaining 725 } 726 727 // TODO, make this more efficient toIndex(double zeroToOne)728 public int toIndex(double zeroToOne) { 729 double weight = zeroToOne * total; 730 int i; 731 for (i = 0; i < weights.length; ++i) { 732 weight -= weights[i]; 733 if (weight <= 0) break; 734 } 735 return i + minCount; 736 } 737 738 @Override toString()739 public String toString() { 740 String result = ""; 741 for (int i = 0; i < minCount; ++i) { 742 if (result.length() != 0) result += ","; 743 result += "0"; 744 } 745 for (int i = 0; i < weights.length; ++i) { 746 if (result.length() != 0) result += ","; 747 result += weights[i]; 748 } 749 return result; 750 } 751 } 752 /* 753 private static Pick convert(Object obj) { 754 if (obj instanceof Pick) return (Pick)obj; 755 return new Literal(obj.toString(), false); 756 } 757 */ 758 // Useful statics 759 pick(Random random, int start, int end)760 static public int pick(Random random, int start, int end) { 761 return start + (int) (random.nextDouble() * (end + 1 - start)); 762 } 763 pick(Random random, double start, double end)764 static public double pick(Random random, double start, double end) { 765 return start + (random.nextDouble() * (end + 1 - start)); 766 } 767 pick(Random random, double percent)768 static public boolean pick(Random random, double percent) { 769 return random.nextDouble() <= percent; 770 } 771 pick(Random random, UnicodeSet s)772 static public int pick(Random random, UnicodeSet s) { 773 return s.charAt(pick(random, 0, s.size() - 1)); 774 } 775 pick(Random random, String[] source)776 static public String pick(Random random, String[] source) { 777 return source[pick(random, 0, source.length - 1)]; 778 } 779 780 // these utilities really ought to be in Java 781 realloc(double[] source, int newSize)782 public static double[] realloc(double[] source, int newSize) { 783 double[] temp = new double[newSize]; 784 if (newSize > source.length) newSize = source.length; 785 if (newSize != 0) System.arraycopy(source, 0, temp, 0, newSize); 786 return temp; 787 } 788 realloc(int[] source, int newSize)789 public static int[] realloc(int[] source, int newSize) { 790 int[] temp = new int[newSize]; 791 if (newSize > source.length) newSize = source.length; 792 if (newSize != 0) System.arraycopy(source, 0, temp, 0, newSize); 793 return temp; 794 } 795 realloc(Pick[] source, int newSize)796 public static Pick[] realloc(Pick[] source, int newSize) { 797 Pick[] temp = new Pick[newSize]; 798 if (newSize > source.length) newSize = source.length; 799 if (newSize != 0) System.arraycopy(source, 0, temp, 0, newSize); 800 return temp; 801 } 802 803 // test utilities 804 /*private static void append(StringBuffer target, String toAdd, StringBuffer quoteBuffer) { 805 Utility.appendToRule(target, (int)-1, true, false, quoteBuffer); // close previous quote 806 if (DEBUG) System.out.println("\"" + toAdd + "\""); 807 target.append(toAdd); 808 } 809 810 private static void appendQuoted(StringBuffer target, String toAdd, StringBuffer quoteBuffer) { 811 if (DEBUG) System.out.println("\"" + toAdd + "\""); 812 Utility.appendToRule(target, toAdd, false, false, quoteBuffer); 813 }*/ 814 815 /* 816 public static abstract class MatchHandler { 817 public abstract void handleString(String source, int start, int limit); 818 public abstract void handleSequence(String source, int start, int limit); 819 public abstract void handleAlternation(String source, int start, int limit); 820 821 } 822 */ 823 /* 824 // redistributes random value 825 // values are still between 0 and 1, but with a different distribution 826 public interface Spread { 827 public double spread(double value); 828 } 829 830 // give the weight for the high end. 831 // values are linearly scaled according to the weight. 832 static public class SimpleSpread implements Spread { 833 static final Spread FLAT = new SimpleSpread(1.0); 834 boolean flat = false; 835 double aa, bb, cc; 836 public SimpleSpread(double maxWeight) { 837 if (maxWeight > 0.999 && maxWeight < 1.001) { 838 flat = true; 839 } else { 840 double q = (maxWeight - 1.0); 841 aa = -1/q; 842 bb = 1/(q*q); 843 cc = (2.0+q)/q; 844 } 845 } 846 public double spread(double value) { 847 if (flat) return value; 848 value = aa + Math.sqrt(bb + cc*value); 849 if (value < 0.0) return 0.0; // catch math gorp 850 if (value >= 1.0) return 1.0; 851 return value; 852 } 853 } 854 static public int pick(Spread spread, Random random, int start, int end) { 855 return start + (int)(spread.spread(random.nextDouble()) * (end + 1 - start)); 856 } 857 858 */ 859 860 }