formatting
[vamsas.git] / src / uk / ac / vamsas / objects / utils / MapList.java
1 /*\r
2  * This file is part of the Vamsas Client version 0.2. \r
3  * Copyright 2010 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]; // last position in fromEnd\r
455     int endindx = (fromRatio2 - 1); // additional positions to get to last\r
456     // position from endpos\r
457     int intv = 0, intvSize = fromShifts2.size();\r
458     int iv[], i = 0, fs = -1, fe_s = -1, fe = -1; // containing intervals\r
459     // search intervals to locate ones containing startpos and count endindx\r
460     // positions on from endpos\r
461     while (intv < intvSize && (fs == -1 || fe == -1)) {\r
462       iv = (int[]) fromShifts2.elementAt(intv++);\r
463       if (fe_s > -1) {\r
464         endpos = iv[0]; // start counting from beginning of interval\r
465         endindx--; // inclusive of endpos\r
466       }\r
467       if (iv[0] <= iv[1]) {\r
468         if (fs == -1 && startpos >= iv[0] && startpos <= iv[1]) {\r
469           fs = i;\r
470         }\r
471         if (endpos >= iv[0] && endpos <= iv[1]) {\r
472           if (fe_s == -1) {\r
473             fe_s = i;\r
474           }\r
475           if (fe_s != -1) {\r
476             if (endpos + endindx <= iv[1]) {\r
477               fe = i;\r
478               endpos = endpos + endindx; // end of end token is within this\r
479               // interval\r
480             } else {\r
481               endindx -= iv[1] - endpos; // skip all this interval too\r
482             }\r
483           }\r
484         }\r
485       } else {\r
486         if (fs == -1 && startpos <= iv[0] && startpos >= iv[1]) {\r
487           fs = i;\r
488         }\r
489         if (endpos <= iv[0] && endpos >= iv[1]) {\r
490           if (fe_s == -1) {\r
491             fe_s = i;\r
492           }\r
493           if (fe_s != -1) {\r
494             if (endpos - endindx >= iv[1]) {\r
495               fe = i;\r
496               endpos = endpos - endindx; // end of end token is within this\r
497               // interval\r
498             } else {\r
499               endindx -= endpos - iv[1]; // skip all this interval too\r
500             }\r
501           }\r
502         }\r
503       }\r
504       i++;\r
505     }\r
506     if (fs == fe && fe == -1)\r
507       return null;\r
508     Vector ranges = new Vector();\r
509     if (fs <= fe) {\r
510       intv = fs;\r
511       i = fs;\r
512       // truncate initial interval\r
513       iv = (int[]) fromShifts2.elementAt(intv++);\r
514       iv = new int[] { iv[0], iv[1] };// clone\r
515       if (i == fs)\r
516         iv[0] = startpos;\r
517       while (i != fe) {\r
518         ranges.addElement(iv); // add initial range\r
519         iv = (int[]) fromShifts2.elementAt(intv++); // get next interval\r
520         iv = new int[] { iv[0], iv[1] };// clone\r
521         i++;\r
522       }\r
523       if (i == fe)\r
524         iv[1] = endpos;\r
525       ranges.addElement(iv); // add only - or final range\r
526     } else {\r
527       // walk from end of interval.\r
528       i = fromShifts2.size() - 1;\r
529       while (i > fs) {\r
530         i--;\r
531       }\r
532       iv = (int[]) fromShifts2.elementAt(i);\r
533       iv = new int[] { iv[1], iv[0] };// reverse and clone\r
534       // truncate initial interval\r
535       if (i == fs) {\r
536         iv[0] = startpos;\r
537       }\r
538       while (--i != fe) { // fix apparent logic bug when fe==-1\r
539         ranges.addElement(iv); // add (truncated) reversed interval\r
540         iv = (int[]) fromShifts2.elementAt(i);\r
541         iv = new int[] { iv[1], iv[0] }; // reverse and clone\r
542       }\r
543       if (i == fe) {\r
544         // interval is already reversed\r
545         iv[1] = endpos;\r
546       }\r
547       ranges.addElement(iv); // add only - or final range\r
548     }\r
549     // create array of start end intervals.\r
550     int[] range = null;\r
551     if (ranges != null && ranges.size() > 0) {\r
552       range = new int[ranges.size() * 2];\r
553       intv = 0;\r
554       intvSize = ranges.size();\r
555       i = 0;\r
556       while (intv < intvSize) {\r
557         iv = (int[]) ranges.elementAt(intv);\r
558         range[i++] = iv[0];\r
559         range[i++] = iv[1];\r
560         ranges.setElementAt(null, intv++); // remove\r
561       }\r
562     }\r
563     return range;\r
564   }\r
565 \r
566   /**\r
567    * get the 'initial' position of mpos in To\r
568    * \r
569    * @param mpos\r
570    *          position in from\r
571    * @return position of first word in to reference frame\r
572    */\r
573   public int getToPosition(int mpos) {\r
574     int[] mp = shiftTo(mpos);\r
575     if (mp != null) {\r
576       return mp[0];\r
577     }\r
578     return mpos;\r
579   }\r
580 \r
581   /**\r
582    * get range of positions in To frame for the mpos word in From\r
583    * \r
584    * @param mpos\r
585    *          position in From\r
586    * @return null or int[] first position in To for mpos, last position in to\r
587    *         for Mpos\r
588    */\r
589   public int[] getToWord(int mpos) {\r
590     int[] mp = shiftTo(mpos);\r
591     if (mp != null) {\r
592       return new int[] { mp[0], mp[0] + mp[2] * (getFromRatio() - 1) };\r
593     }\r
594     return null;\r
595   }\r
596 \r
597   /**\r
598    * get From position in the associated reference frame for position pos in the\r
599    * associated sequence.\r
600    * \r
601    * @param pos\r
602    * @return\r
603    */\r
604   public int getMappedPosition(int pos) {\r
605     int[] mp = shiftFrom(pos);\r
606     if (mp != null) {\r
607       return mp[0];\r
608     }\r
609     return pos;\r
610   }\r
611 \r
612   public int[] getMappedWord(int pos) {\r
613     int[] mp = shiftFrom(pos);\r
614     if (mp != null) {\r
615       return new int[] { mp[0], mp[0] + mp[2] * (getToRatio() - 1) };\r
616     }\r
617     return null;\r
618   }\r
619 \r
620   /**\r
621    * test routine. not incremental.\r
622    * \r
623    * @param ml\r
624    * @param fromS\r
625    * @param fromE\r
626    */\r
627   public static void testMap(MapList ml, int fromS, int fromE) {\r
628     for (int from = 1; from <= 25; from++) {\r
629       int[] too = ml.shiftFrom(from);\r
630       System.out.print("ShiftFrom(" + from + ")==");\r
631       if (too == null) {\r
632         System.out.print("NaN\n");\r
633       } else {\r
634         System.out.print(too[0] + " % " + too[1] + " (" + too[2] + ")");\r
635         System.out.print("\t+--+\t");\r
636         int[] toofrom = ml.shiftTo(too[0]);\r
637         if (toofrom != null) {\r
638           if (toofrom[0] != from) {\r
639             System.err.println("Mapping not reflexive:" + from + " " + too[0]\r
640                 + "->" + toofrom[0]);\r
641           }\r
642           System.out.println("ShiftTo(" + too[0] + ")==" + toofrom[0] + " % "\r
643               + toofrom[1] + " (" + toofrom[2] + ")");\r
644         } else {\r
645           System.out.println("ShiftTo(" + too[0] + ")=="\r
646               + "NaN! - not Bijective Mapping!");\r
647         }\r
648       }\r
649     }\r
650     int mmap[][] = ml.makeFromMap();\r
651     System.out.println("FromMap : (" + mmap[0][0] + " " + mmap[0][1] + " "\r
652         + mmap[0][2] + " " + mmap[0][3] + " ");\r
653     for (int i = 1; i <= mmap[1].length; i++) {\r
654       if (mmap[1][i - 1] == -1) {\r
655         System.out.print(i + "=XXX");\r
656 \r
657       } else {\r
658         System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));\r
659       }\r
660       if (i % 20 == 0) {\r
661         System.out.print("\n");\r
662       } else {\r
663         System.out.print(",");\r
664       }\r
665     }\r
666     // test range function\r
667     System.out.print("\nTest locateInFrom\n");\r
668     {\r
669       int f = mmap[0][2], t = mmap[0][3];\r
670       while (f <= t) {\r
671         System.out.println("Range " + f + " to " + t);\r
672         int rng[] = ml.locateInFrom(f, t);\r
673         if (rng != null) {\r
674           for (int i = 0; i < rng.length; i++) {\r
675             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
676           }\r
677         } else {\r
678           System.out.println("No range!");\r
679         }\r
680         System.out.print("\nReversed\n");\r
681         rng = ml.locateInFrom(t, f);\r
682         if (rng != null) {\r
683           for (int i = 0; i < rng.length; i++) {\r
684             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
685           }\r
686         } else {\r
687           System.out.println("No range!");\r
688         }\r
689         System.out.print("\n");\r
690         f++;\r
691         t--;\r
692       }\r
693     }\r
694     System.out.print("\n");\r
695     mmap = ml.makeToMap();\r
696     System.out.println("ToMap : (" + mmap[0][0] + " " + mmap[0][1] + " "\r
697         + mmap[0][2] + " " + mmap[0][3] + " ");\r
698     for (int i = 1; i <= mmap[1].length; i++) {\r
699       if (mmap[1][i - 1] == -1) {\r
700         System.out.print(i + "=XXX");\r
701 \r
702       } else {\r
703         System.out.print(i + "=" + (mmap[0][2] + mmap[1][i - 1]));\r
704       }\r
705       if (i % 20 == 0) {\r
706         System.out.print("\n");\r
707       } else {\r
708         System.out.print(",");\r
709       }\r
710     }\r
711     System.out.print("\n");\r
712     // test range function\r
713     System.out.print("\nTest locateInTo\n");\r
714     {\r
715       int f = mmap[0][2], t = mmap[0][3];\r
716       while (f <= t) {\r
717         System.out.println("Range " + f + " to " + t);\r
718         int rng[] = ml.locateInTo(f, t);\r
719         if (rng != null) {\r
720           for (int i = 0; i < rng.length; i++) {\r
721             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
722           }\r
723         } else {\r
724           System.out.println("No range!");\r
725         }\r
726         System.out.print("\nReversed\n");\r
727         rng = ml.locateInTo(t, f);\r
728         if (rng != null) {\r
729           for (int i = 0; i < rng.length; i++) {\r
730             System.out.print(rng[i] + ((i % 2 == 0) ? "," : ";"));\r
731           }\r
732         } else {\r
733           System.out.println("No range!");\r
734         }\r
735         f++;\r
736         t--;\r
737         System.out.print("\n");\r
738       }\r
739     }\r
740 \r
741   }\r
742 \r
743   public static void main(String argv[]) {\r
744     MapList ml = new MapList(new int[] { 1, 5, 10, 15, 25, 20 }, new int[] {\r
745         51, 1 }, 1, 3);\r
746     MapList ml1 = new MapList(new int[] { 1, 3, 17, 4 }, new int[] { 51, 1 },\r
747         1, 3);\r
748     MapList ml2 = new MapList(new int[] { 1, 60 }, new int[] { 1, 20 }, 3, 1);\r
749     // test internal consistency\r
750     int to[] = new int[51];\r
751     MapList.testMap(ml, 1, 60);\r
752     MapList mldna = new MapList(new int[] { 2, 2, 6, 8, 12, 16 }, new int[] {\r
753         1, 3 }, 3, 1);\r
754     int[] frm = mldna.locateInFrom(1, 1);\r
755     testLocateFrom(mldna, 1, 1, new int[] { 2, 2, 6, 7 });\r
756     MapList.testMap(mldna, 1, 3);\r
757     /*\r
758      * for (int from=1; from<=51; from++) { int[] too=ml.shiftTo(from); int[]\r
759      * toofrom=ml.shiftFrom(too[0]);\r
760      * System.out.println("ShiftFrom("+from+")=="+too\r
761      * [0]+" % "+too[1]+"\t+-+\tShiftTo("\r
762      * +too[0]+")=="+toofrom[0]+" % "+toofrom[1]); }\r
763      */\r
764     System.out.print("Success?\n"); // if we get here - something must be\r
765     // working!\r
766   }\r
767 \r
768   private static void testLocateFrom(MapList mldna, int i, int j, int[] ks) {\r
769     int[] frm = mldna.locateInFrom(i, j);\r
770     if (frm == ks || java.util.Arrays.equals(frm, ks)) {\r
771       System.out.println("Success test locate from " + i + " to " + j);\r
772     } else {\r
773       System.err.println("Failed test locate from " + i + " to " + j);\r
774       for (int c = 0; c < frm.length; c++) {\r
775         System.err.print(frm[c] + ((c % 2 == 0) ? "," : ";"));\r
776       }\r
777       System.err.println("Expected");\r
778       for (int c = 0; c < ks.length; c++) {\r
779         System.err.print(ks[c] + ((c % 2 == 0) ? "," : ";"));\r
780       }\r
781     }\r
782   }\r
783 \r
784   /**\r
785    * \r
786    * @return a MapList whose From range is this maplist's To Range, and vice\r
787    *         versa\r
788    */\r
789   public MapList getInverse() {\r
790     return new MapList(getToRanges(), getFromRanges(), getToRatio(),\r
791         getFromRatio());\r
792   }\r
793 \r
794   /**\r
795    * test for containment rather than equivalence to another mapping\r
796    * \r
797    * @param map\r
798    *          to be tested for containment\r
799    * @return true if local or mapped range map contains or is contained by this\r
800    *         mapping\r
801    */\r
802   public boolean containsEither(boolean local, MapList map) {\r
803     if (local) {\r
804       return ((getFromLowest() >= map.getFromLowest() && getFromHighest() <= map\r
805           .getFromHighest()) || (getFromLowest() <= map.getFromLowest() && getFromHighest() >= map\r
806           .getFromHighest()));\r
807     } else {\r
808       return ((getToLowest() >= map.getToLowest() && getToHighest() <= map\r
809           .getToHighest()) || (getToLowest() <= map.getToLowest() && getToHighest() >= map\r
810           .getToHighest()));\r
811     }\r
812   }\r
813 }\r