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