applied LGPLv3 and source code formatting.
[vamsas.git] / src / uk / ac / vamsas / objects / utils / MapList.java
1 /*\r
2  * This file is part of the Vamsas Client version 0.1. \r
3  * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, \r
4  *  Andrew Waterhouse and Dominik Lindner.\r
5  * \r
6  * Earlier versions have also been incorporated into Jalview version 2.4 \r
7  * since 2008, and TOPALi version 2 since 2007.\r
8  * \r
9  * The Vamsas Client is free software: you can redistribute it and/or modify\r
10  * it under the terms of the GNU Lesser General Public License as published by\r
11  * the Free Software Foundation, either version 3 of the License, or\r
12  * (at your option) any later version.\r
13  *  \r
14  * The Vamsas Client is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17  * GNU Lesser General Public License for more details.\r
18  * \r
19  * You should have received a copy of the GNU Lesser General Public License\r
20  * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.\r
21  */\r
22 package uk.ac.vamsas.objects.utils;\r
23 \r
24 import java.util.*;\r
25 \r
26 /**\r
27  * MapList Simple way of bijectively mapping a non-contiguous linear range to\r
28  * another non-contiguous linear range Use at your own risk! TODO: efficient\r
29  * implementation of private posMap method TODO: test/ensure that sense of from\r
30  * and to ratio start position is conserved (codon start position recovery)\r
31  * TODO: optimize to use int[][] arrays rather than vectors.\r
32  */\r
33 public class MapList {\r
34   /*\r
35    * (non-Javadoc)\r
36    * \r
37    * @see java.lang.Object#equals(java.lang.Object)\r
38    */\r
39   public boolean equals(MapList obj) {\r
40     if (obj == this)\r
41       return true;\r
42     if (obj != null && obj.fromRatio == fromRatio && obj.toRatio == toRatio\r
43         && obj.fromShifts != null && obj.toShifts != null) {\r
44       int i, iSize = fromShifts.size(), j, jSize = obj.fromShifts.size();\r
45       if (iSize != jSize)\r
46         return false;\r
47       for (i = 0, iSize = fromShifts.size(), j = 0, jSize = obj.fromShifts\r
48           .size(); i < iSize;) {\r
49         int[] mi = (int[]) fromShifts.elementAt(i++);\r
50         int[] mj = (int[]) obj.fromShifts.elementAt(j++);\r
51         if (mi[0] != mj[0] || mi[1] != mj[1])\r
52           return false;\r
53       }\r
54       iSize = toShifts.size();\r
55       jSize = obj.toShifts.size();\r
56       if (iSize != jSize)\r
57         return false;\r
58       for (i = 0, j = 0; i < iSize;) {\r
59         int[] mi = (int[]) toShifts.elementAt(i++);\r
60         int[] mj = (int[]) obj.toShifts.elementAt(j++);\r
61         if (mi[0] != mj[0] || mi[1] != mj[1])\r
62           return false;\r
63       }\r
64       return true;\r
65     }\r
66     return false;\r
67   }\r
68 \r
69   public Vector fromShifts;\r
70 \r
71   public Vector toShifts;\r
72 \r
73   int fromRatio; // number of steps in fromShifts to one toRatio unit\r
74 \r
75   int toRatio; // number of steps in toShifts to one fromRatio\r
76 \r
77   /**\r
78    * \r
79    * @return series of intervals mapped in from\r
80    */\r
81   public int[] getFromRanges() {\r
82     return getRanges(fromShifts);\r
83   }\r
84 \r
85   public int[] getToRanges() {\r
86     return getRanges(toShifts);\r
87   }\r
88 \r
89   private int[] getRanges(Vector shifts) {\r
90     int[] rnges = new int[2 * shifts.size()];\r
91     Enumeration e = shifts.elements();\r
92     int i = 0;\r
93     while (e.hasMoreElements()) {\r
94       int r[] = (int[]) e.nextElement();\r
95       rnges[i++] = r[0];\r
96       rnges[i++] = r[1];\r
97     }\r
98     return rnges;\r
99   }\r
100 \r
101   /**\r
102    * lowest and highest value in the from Map\r
103    */\r
104   int[] fromRange = null;\r
105 \r
106   /**\r
107    * lowest and highest value in the to Map\r
108    */\r
109   int[] toRange = null;\r
110 \r
111   /**\r
112    * \r
113    * @return length of mapped phrase in from\r
114    */\r
115   public int getFromRatio() {\r
116     return fromRatio;\r
117   }\r
118 \r
119   /**\r
120    * \r
121    * @return length of mapped phrase in to\r
122    */\r
123   public int getToRatio() {\r
124     return toRatio;\r
125   }\r
126 \r
127   public int getFromLowest() {\r
128     return fromRange[0];\r
129   }\r
130 \r
131   public int getFromHighest() {\r
132     return fromRange[1];\r
133   }\r
134 \r
135   public int getToLowest() {\r
136     return toRange[0];\r
137   }\r
138 \r
139   public int getToHighest() {\r
140     return toRange[1];\r
141   }\r
142 \r
143   private void ensureRange(int[] limits, int pos) {\r
144     if (limits[0] > pos)\r
145       limits[0] = pos;\r
146     if (limits[1] < pos)\r
147       limits[1] = pos;\r
148   }\r
149 \r
150   public MapList(int from[], int to[], int fromRatio, int toRatio) {\r
151     fromRange = new int[] { from[0], from[1] };\r
152     toRange = new int[] { to[0], to[1] };\r
153 \r
154     fromShifts = new Vector();\r
155     for (int i = 0; i < from.length; i += 2) {\r
156       ensureRange(fromRange, from[i]);\r
157       ensureRange(fromRange, from[i + 1]);\r
158 \r
159       fromShifts.addElement(new int[] { from[i], from[i + 1] });\r
160     }\r
161     toShifts = new Vector();\r
162     for (int i = 0; i < to.length; i += 2) {\r
163       ensureRange(toRange, to[i]);\r
164       ensureRange(toRange, to[i + 1]);\r
165       toShifts.addElement(new int[] { to[i], to[i + 1] });\r
166     }\r
167     this.fromRatio = fromRatio;\r
168     this.toRatio = toRatio;\r
169   }\r
170 \r
171   public MapList(MapList map) {\r
172     this.fromRange = new int[] { map.fromRange[0], map.fromRange[1] };\r
173     this.toRange = new int[] { map.toRange[0], map.toRange[1] };\r
174     this.fromRatio = map.fromRatio;\r
175     this.toRatio = map.toRatio;\r
176     if (map.fromShifts != null) {\r
177       this.fromShifts = new Vector();\r
178       Enumeration e = map.fromShifts.elements();\r
179       while (e.hasMoreElements()) {\r
180         int[] el = (int[]) e.nextElement();\r
181         fromShifts.addElement(new int[] { el[0], el[1] });\r
182       }\r
183     }\r
184     if (map.toShifts != null) {\r
185       this.toShifts = new Vector();\r
186       Enumeration e = map.toShifts.elements();\r
187       while (e.hasMoreElements()) {\r
188         int[] el = (int[]) e.nextElement();\r
189         toShifts.addElement(new int[] { el[0], el[1] });\r
190       }\r
191     }\r
192   }\r
193 \r
194   /**\r
195    * get all mapped positions from 'from' to 'to'\r
196    * \r
197    * @return int[][] { int[] { fromStart, fromFinish, toStart, toFinish }, int\r
198    *         [fromFinish-fromStart+2] { toStart..toFinish mappings}}\r
199    */\r
200   public int[][] makeFromMap() {\r
201     return posMap(fromShifts, fromRatio, toShifts, toRatio);\r
202   }\r
203 \r
204   /**\r
205    * get all mapped positions from 'to' to 'from'\r
206    * \r
207    * @return int[to position]=position mapped in from\r
208    */\r
209   public int[][] makeToMap() {\r
210     return posMap(toShifts, toRatio, fromShifts, fromRatio);\r
211   }\r
212 \r
213   /**\r
214    * construct an int map for intervals in intVals\r
215    * \r
216    * @param intVals\r
217    * @return int[] { from, to pos in range }, int[range.to-range.from+1]\r
218    *         returning mapped position\r
219    */\r
220   private int[][] posMap(Vector intVals, int ratio, Vector toIntVals,\r
221       int toRatio) {\r
222     int iv = 0, ivSize = intVals.size();\r
223     if (iv >= ivSize) {\r
224       return null;\r
225     }\r
226     int[] intv = (int[]) intVals.elementAt(iv++);\r
227     int from = intv[0], to = intv[1];\r
228     if (from > to) {\r
229       from = intv[1];\r
230       to = intv[0];\r
231     }\r
232     while (iv < ivSize) {\r
233       intv = (int[]) intVals.elementAt(iv++);\r
234       if (intv[0] < from) {\r
235         from = intv[0];\r
236       }\r
237       if (intv[1] < from) {\r
238         from = intv[1];\r
239       }\r
240       if (intv[0] > to) {\r
241         to = intv[0];\r
242       }\r
243       if (intv[1] > to) {\r
244         to = intv[1];\r
245       }\r
246     }\r
247     int tF = 0, tT = 0;\r
248     int mp[][] = new int[to - from + 2][];\r
249     for (int i = 0; i < mp.length; i++) {\r
250       int[] m = shift(i + from, intVals, ratio, toIntVals, toRatio);\r
251       if (m != null) {\r
252         if (i == 0) {\r
253           tF = tT = m[0];\r
254         } else {\r
255           if (m[0] < tF) {\r
256             tF = m[0];\r
257           }\r
258           if (m[0] > tT) {\r
259             tT = m[0];\r
260           }\r
261         }\r
262       }\r
263       mp[i] = m;\r
264     }\r
265     int[][] map = new int[][] { new int[] { from, to, tF, tT },\r
266         new int[to - from + 2] };\r
267 \r
268     map[0][2] = tF;\r
269     map[0][3] = tT;\r
270 \r
271     for (int i = 0; i < mp.length; i++) {\r
272       if (mp[i] != null) {\r
273         map[1][i] = mp[i][0] - tF;\r
274       } else {\r
275         map[1][i] = -1; // indicates an out of range mapping\r
276       }\r
277     }\r
278     return map;\r
279   }\r
280 \r
281   /**\r
282    * addShift\r
283    * \r
284    * @param pos\r
285    *          start position for shift (in original reference frame)\r
286    * @param shift\r
287    *          length of shift\r
288    * \r
289    *          public void addShift(int pos, int shift) { int sidx = 0; int[]\r
290    *          rshift=null; while (sidx<shifts.size() && (rshift=(int[])\r
291    *          shifts.elementAt(sidx))[0]<pos) sidx++; if (sidx==shifts.size())\r
292    *          shifts.insertElementAt(new int[] { pos, shift}, sidx); else\r
293    *          rshift[1]+=shift; }\r
294    */\r
295   /**\r
296    * shift from pos to To(pos)\r
297    * \r
298    * @param pos\r
299    *          int\r
300    * @return int shifted position in To, frameshift in From, direction of mapped\r
301    *         symbol in To\r
302    */\r
303   public int[] shiftFrom(int pos) {\r
304     return shift(pos, fromShifts, fromRatio, toShifts, toRatio);\r
305   }\r
306 \r
307   /**\r
308    * inverse of shiftFrom - maps pos in To to a position in From\r
309    * \r
310    * @param pos\r
311    *          (in To)\r
312    * @return shifted position in From, frameshift in To, direction of mapped\r
313    *         symbol in From\r
314    */\r
315   public int[] shiftTo(int pos) {\r
316     return shift(pos, toShifts, toRatio, fromShifts, fromRatio);\r
317   }\r
318 \r
319   /**\r
320    * \r
321    * @param fromShifts\r
322    * @param fromRatio\r
323    * @param toShifts\r
324    * @param toRatio\r
325    * @return\r
326    */\r
327   private int[] shift(int pos, Vector fromShifts, int fromRatio,\r
328       Vector toShifts, int toRatio) {\r
329     int[] fromCount = countPos(fromShifts, pos);\r
330     if (fromCount == null) {\r
331       return null;\r
332     }\r
333     int fromRemainder = (fromCount[0] - 1) % fromRatio;\r
334     int toCount = 1 + (((fromCount[0] - 1) / fromRatio) * toRatio);\r
335     int[] toPos = countToPos(toShifts, toCount);\r
336     if (toPos == null) {\r
337       return null; // throw new Error("Bad Mapping!");\r
338     }\r
339     // System.out.println(fromCount[0]+" "+fromCount[1]+" "+toCount);\r
340     return new int[] { toPos[0], fromRemainder, toPos[1] };\r
341   }\r
342 \r
343   /**\r
344    * count how many positions pos is along the series of intervals.\r
345    * \r
346    * @param intVals\r
347    * @param pos\r
348    * @return number of positions or null if pos is not within intervals\r
349    */\r
350   private int[] countPos(Vector intVals, int pos) {\r
351     int count = 0, intv[], iv = 0, ivSize = intVals.size();\r
352     while (iv < ivSize) {\r
353       intv = (int[]) intVals.elementAt(iv++);\r
354       if (intv[0] <= intv[1]) {\r
355         if (pos >= intv[0] && pos <= intv[1]) {\r
356           return new int[] { count + pos - intv[0] + 1, +1 };\r
357         } else {\r
358           count += intv[1] - intv[0] + 1;\r
359         }\r
360       } else {\r
361         if (pos >= intv[1] && pos <= intv[0]) {\r
362           return new int[] { count + intv[0] - pos + 1, -1 };\r
363         } else {\r
364           count += intv[0] - intv[1] + 1;\r
365         }\r
366       }\r
367     }\r
368     return null;\r
369   }\r
370 \r
371   /**\r
372    * count out pos positions into a series of intervals and return the position\r
373    * \r
374    * @param intVals\r
375    * @param pos\r
376    * @return position pos in interval set\r
377    */\r
378   private int[] countToPos(Vector intVals, int pos) {\r
379     int count = 0, diff = 0, iv = 0, ivSize = intVals.size(), intv[] = { 0, 0 };\r
380     while (iv < ivSize) {\r
381       intv = (int[]) intVals.elementAt(iv++);\r
382       diff = intv[1] - intv[0];\r
383       if (diff >= 0) {\r
384         if (pos <= count + 1 + diff) {\r
385           return new int[] { pos - count - 1 + intv[0], +1 };\r
386         } else {\r
387           count += 1 + diff;\r
388         }\r
389       } else {\r
390         if (pos <= count + 1 - diff) {\r
391           return new int[] { intv[0] - (pos - count - 1), -1 };\r
392         } else {\r
393           count += 1 - diff;\r
394         }\r
395       }\r
396     }\r
397     return null;// (diff<0) ? (intv[1]-1) : (intv[0]+1);\r
398   }\r
399 \r
400   /**\r
401    * find series of intervals mapping from start-end in the From map.\r
402    * \r
403    * @param start\r
404    *          position in to map\r
405    * @param end\r
406    *          position in to map\r
407    * @return series of ranges in from map\r
408    */\r
409   public int[] locateInFrom(int start, int end) {\r
410     // inefficient implementation\r
411     int fromStart[] = shiftTo(start);\r
412     int fromEnd[] = shiftTo(end); // needs to be inclusive of end of symbol\r
413                                   // position\r
414     if (fromStart == null || fromEnd == null)\r
415       return null;\r
416     int iv[] = getIntervals(fromShifts, fromStart, fromEnd, fromRatio);\r
417     return iv;\r
418   }\r
419 \r
420   /**\r
421    * find series of intervals mapping from start-end in the to map.\r
422    * \r
423    * @param start\r
424    *          position in from map\r
425    * @param end\r
426    *          position in from map\r
427    * @return series of ranges in to map\r
428    */\r
429   public int[] locateInTo(int start, int end) {\r
430     // inefficient implementation\r
431     int toStart[] = shiftFrom(start);\r
432     int toEnd[] = shiftFrom(end);\r
433     if (toStart == null || toEnd == null)\r
434       return null;\r
435     int iv[] = getIntervals(toShifts, toStart, toEnd, toRatio);\r
436     return iv;\r
437   }\r
438 \r
439   /**\r
440    * like shift - except returns the intervals in the given vector of shifts\r
441    * which were spanned in traversing fromStart to fromEnd\r
442    * \r
443    * @param fromShifts2\r
444    * @param fromStart\r
445    * @param fromEnd\r
446    * @param fromRatio2\r
447    * @return series of from,to intervals from from first position of starting\r
448    *         region to final position of ending region inclusive\r
449    */\r
450   private int[] getIntervals(Vector fromShifts2, int[] fromStart,\r
451       int[] fromEnd, int fromRatio2) {\r
452     int startpos, endpos;\r
453     startpos = fromStart[0]; // first position in fromStart\r
454     endpos = fromEnd[0] + fromEnd[2] * (fromRatio2 - 1); // last position in\r
455                                                          // fromEnd\r
456     int intv = 0, intvSize = fromShifts2.size();\r
457     int iv[], i = 0, fs = -1, fe = -1; // containing intervals\r
458     while (intv < intvSize && (fs == -1 || fe == -1)) {\r
459       iv = (int[]) fromShifts2.elementAt(intv++);\r
460       if (iv[0] <= iv[1]) {\r
461         if (fs == -1 && startpos >= iv[0] && startpos <= iv[1]) {\r
462           fs = i;\r
463         }\r
464         if (fe == -1 && endpos >= iv[0] && endpos <= iv[1]) {\r
465           fe = i;\r
466         }\r
467       } else {\r
468         if (fs == -1 && startpos <= iv[0] && startpos >= iv[1]) {\r
469           fs = i;\r
470         }\r
471         if (fe == -1 && endpos <= iv[0] && endpos >= iv[1]) {\r
472           fe = i;\r
473         }\r
474       }\r
475       i++;\r
476     }\r
477     if (fs == fe && fe == -1)\r
478       return null;\r
479     Vector ranges = new Vector();\r
480     if (fs <= fe) {\r
481       intv = fs;\r
482       i = fs;\r
483       // truncate initial interval\r
484       iv = (int[]) fromShifts2.elementAt(intv++);\r
485       iv = new int[] { iv[0], iv[1] };// clone\r
486       if (i == fs)\r
487         iv[0] = startpos;\r
488       while (i != fe) {\r
489         ranges.addElement(iv); // add initial range\r
490         iv = (int[]) fromShifts2.elementAt(intv++); // get next interval\r
491         iv = new int[] { iv[0], iv[1] };// clone\r
492         i++;\r
493       }\r
494       if (i == fe)\r
495         iv[1] = endpos;\r
496       ranges.addElement(iv); // add only - or final range\r
497     } else {\r
498       // walk from end of interval.\r
499       i = fromShifts2.size() - 1;\r
500       while (i > fs) {\r
501         i--;\r
502       }\r
503       iv = (int[]) fromShifts2.elementAt(i);\r
504       iv = new int[] { iv[1], iv[0] };// reverse and clone\r
505       // truncate initial interval\r
506       if (i == fs) {\r
507         iv[0] = startpos;\r
508       }\r
509       while (--i != fe) { // fix apparent logic bug when fe==-1\r
510         ranges.addElement(iv); // add (truncated) reversed interval\r
511         iv = (int[]) fromShifts2.elementAt(i);\r
512         iv = new int[] { iv[1], iv[0] }; // reverse and clone\r
513       }\r
514       if (i == fe) {\r
515         // interval is already reversed\r
516         iv[1] = endpos;\r
517       }\r
518       ranges.addElement(iv); // add only - or final range\r
519     }\r
520     // create array of start end intervals.\r
521     int[] range = null;\r
522     if (ranges != null && ranges.size() > 0) {\r
523       range = new int[ranges.size() * 2];\r
524       intv = 0;\r
525       intvSize = ranges.size();\r
526       i = 0;\r
527       while (intv < intvSize) {\r
528         iv = (int[]) ranges.elementAt(intv);\r
529         range[i++] = iv[0];\r
530         range[i++] = iv[1];\r
531         ranges.setElementAt(null, intv++); // remove\r
532       }\r
533     }\r
534     return range;\r
535   }\r
536 \r
537   /**\r
538    * get the 'initial' position of mpos in To\r
539    * \r
540    * @param mpos\r
541    *          position in from\r
542    * @return position of first word in to reference frame\r
543    */\r
544   public int getToPosition(int mpos) {\r
545     int[] mp = shiftTo(mpos);\r
546     if (mp != null) {\r
547       return mp[0];\r
548     }\r
549     return mpos;\r
550   }\r
551 \r
552   /**\r
553    * get range of positions in To frame for the mpos word in From\r
554    * \r
555    * @param mpos\r
556    *          position in From\r
557    * @return null or int[] first position in To for mpos, last position in to\r
558    *         for Mpos\r
559    */\r
560   public int[] getToWord(int mpos) {\r
561     int[] mp = shiftTo(mpos);\r
562     if (mp != null) {\r
563       return new int[] { mp[0], mp[0] + mp[2] * (getFromRatio() - 1) };\r
564     }\r
565     return null;\r
566   }\r
567 \r
568   /**\r
569    * get From position in the associated reference frame for position pos in the\r
570    * associated sequence.\r
571    * \r
572    * @param pos\r
573    * @return\r
574    */\r
575   public int getMappedPosition(int pos) {\r
576     int[] mp = shiftFrom(pos);\r
577     if (mp != null) {\r
578       return mp[0];\r
579     }\r
580     return pos;\r
581   }\r
582 \r
583   public int[] getMappedWord(int pos) {\r
584     int[] mp = shiftFrom(pos);\r
585     if (mp != null) {\r
586       return new int[] { mp[0], mp[0] + mp[2] * (getToRatio() - 1) };\r
587     }\r
588     return null;\r
589   }\r
590 \r
591   /**\r
592    * test routine. not incremental.\r
593    * \r
594    * @param ml\r
595    * @param fromS\r
596    * @param fromE\r
597    */\r
598   public static void testMap(MapList ml, int fromS, int fromE) {\r
599     for (int from = 1; from <= 25; from++) {\r
600       int[] too = ml.shiftFrom(from);\r
601       System.out.print("ShiftFrom(" + from + ")==");\r
602       if (too == null) {\r
603         System.out.print("NaN\n");\r
604       } else {\r
605         System.out.print(too[0] + " % " + too[1] + " (" + too[2] + ")");\r
606         System.out.print("\t+--+\t");\r
607         int[] toofrom = ml.shiftTo(too[0]);\r
608         if (toofrom != null) {\r
609           if (toofrom[0] != from) {\r
610             System.err.println("Mapping not reflexive:" + from + " " + too[0]\r
611                 + "->" + toofrom[0]);\r
612           }\r
613           System.out.println("ShiftTo(" + too[0] + ")==" + toofrom[0] + " % "\r
614               + toofrom[1] + " (" + toofrom[2] + ")");\r
615         } else {\r
616           System.out.println("ShiftTo(" + too[0] + ")=="\r
617               + "NaN! - not Bijective Mapping!");\r
618         }\r
619       }\r
620     }\r
621     int mmap[][] = ml.makeFromMap();\r
622     System.out.println("FromMap : (" + mmap[0][0] + " " + mmap[0][1] + " "\r
623         + mmap[0][2] + " " + mmap[0][3] + " ");\r
624     for (int i = 1; i <= mmap[1].length; i++) {\r
625       if (mmap[1][i - 1] == -1) {\r
626         System.out.print(i + "=XXX");\r
627 \r
628       } else {\r
629         System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));\r
630       }\r
631       if (i % 20 == 0) {\r
632         System.out.print("\n");\r
633       } else {\r
634         System.out.print(",");\r
635       }\r
636     }\r
637     // test range function\r
638     System.out.print("\nTest locateInFrom\n");\r
639     {\r
640       int f = mmap[0][2], t = mmap[0][3];\r
641       while (f <= t) {\r
642         System.out.println("Range " + f + " to " + t);\r
643         int rng[] = ml.locateInFrom(f, t);\r
644         if (rng != null) {\r
645           for (int i = 0; i < rng.length; i++) {\r
646             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
647           }\r
648         } else {\r
649           System.out.println("No range!");\r
650         }\r
651         System.out.print("\nReversed\n");\r
652         rng = ml.locateInFrom(t, f);\r
653         if (rng != null) {\r
654           for (int i = 0; i < rng.length; i++) {\r
655             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
656           }\r
657         } else {\r
658           System.out.println("No range!");\r
659         }\r
660         System.out.print("\n");\r
661         f++;\r
662         t--;\r
663       }\r
664     }\r
665     System.out.print("\n");\r
666     mmap = ml.makeToMap();\r
667     System.out.println("ToMap : (" + mmap[0][0] + " " + mmap[0][1] + " "\r
668         + mmap[0][2] + " " + mmap[0][3] + " ");\r
669     for (int i = 1; i <= mmap[1].length; i++) {\r
670       if (mmap[1][i - 1] == -1) {\r
671         System.out.print(i + "=XXX");\r
672 \r
673       } else {\r
674         System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));\r
675       }\r
676       if (i % 20 == 0) {\r
677         System.out.print("\n");\r
678       } else {\r
679         System.out.print(",");\r
680       }\r
681     }\r
682     System.out.print("\n");\r
683     // test range function\r
684     System.out.print("\nTest locateInTo\n");\r
685     {\r
686       int f = mmap[0][2], t = mmap[0][3];\r
687       while (f <= t) {\r
688         System.out.println("Range " + f + " to " + t);\r
689         int rng[] = ml.locateInTo(f, t);\r
690         if (rng != null) {\r
691           for (int i = 0; i < rng.length; i++) {\r
692             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
693           }\r
694         } else {\r
695           System.out.println("No range!");\r
696         }\r
697         System.out.print("\nReversed\n");\r
698         rng = ml.locateInTo(t, f);\r
699         if (rng != null) {\r
700           for (int i = 0; i < rng.length; i++) {\r
701             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
702           }\r
703         } else {\r
704           System.out.println("No range!");\r
705         }\r
706         f++;\r
707         t--;\r
708         System.out.print("\n");\r
709       }\r
710     }\r
711 \r
712   }\r
713 \r
714   public static void main(String argv[]) {\r
715     MapList ml = new MapList(new int[] { 1, 5, 10, 15, 25, 20 }, new int[] {\r
716         51, 1 }, 1, 3);\r
717     MapList ml1 = new MapList(new int[] { 1, 3, 17, 4 }, new int[] { 51, 1 },\r
718         1, 3);\r
719     MapList ml2 = new MapList(new int[] { 1, 60 }, new int[] { 1, 20 }, 3, 1);\r
720     // test internal consistency\r
721     int to[] = new int[51];\r
722     MapList.testMap(ml, 1, 60);\r
723     /*\r
724      * for (int from=1; from<=51; from++) { int[] too=ml.shiftTo(from); int[]\r
725      * toofrom=ml.shiftFrom(too[0]);\r
726      * System.out.println("ShiftFrom("+from+")=="+too\r
727      * [0]+" % "+too[1]+"\t+-+\tShiftTo("\r
728      * +too[0]+")=="+toofrom[0]+" % "+toofrom[1]); }\r
729      */\r
730     System.out.print("Success?\n"); // if we get here - something must be\r
731                                     // working!\r
732   }\r
733 \r
734   /**\r
735    * \r
736    * @return a MapList whose From range is this maplist's To Range, and vice\r
737    *         versa\r
738    */\r
739   public MapList getInverse() {\r
740     return new MapList(getToRanges(), getFromRanges(), getToRatio(),\r
741         getFromRatio());\r
742   }\r
743 }\r