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