package align2; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicLongArray; import stream.SiteScore; import dna.Data; public final class Tools { public static boolean isJavaFlag(String arg){ if(arg==null){return false;} if(arg.startsWith("-Xmx") || arg.startsWith("-Xms") || arg.startsWith("-Xmn") || arg.equals("-ea") || arg.equals("-da")){return true;} if(arg.startsWith("Xmx") || arg.startsWith("Xms") || arg.startsWith("Xmn")){ return arg.length()>3 && Character.isDigit(arg.charAt(3)); } return false; } /** Return true if the user seems confused */ public static boolean parseHelp(String[] args){ if(args==null || args.length==0 || (args.length==1 && args[0]==null)){return true;} if(args.length>1){return false;} final String s=args[0].toLowerCase(); return s.equals("-h") || s.equals("-help") || s.equals("--help") || s.equals("-version") || s.equals("--version") || s.equals("?") || s.equals("-?") || (s.equals("help") && !new File(s).exists()); } /** Checks for permission to overwrite files, and output name collisions. */ public static boolean testOutputFiles(boolean overwrite, boolean allowDuplicates, String...args){ if(args==null || args.length==0){return true;} HashSet set=new HashSet(args.length*2); int terms=0; for(String s : args){ if(s!=null){ if(isOutputFileName(s)){ terms++; if(!overwrite && new File(s).exists()){ assert(overwrite) : "File "+s+" exists and overwrite=false"; return false; } if(!allowDuplicates && set.contains(s)){ assert(false) : "Duplicate file "+s+" was specified for multiple output streams."; return false; } set.add(s); } } } return true; } public static final boolean canWrite(String s, boolean overwrite){ if(isNullFileName(s) || isSpecialOutputName(s)){return true;} File f=new File(s); if(f.exists()){return overwrite && f.canWrite();} return true; } // public static final boolean outputDestinationExists(String s){ // if(isNullFileName(s)){return false;} // if(isSpecialOutputName(s)){return false;} // File f=new File(s); // return f.exists(); // } public static final boolean isOutputFileName(String s){ return !(isNullFileName(s) || isSpecialOutputName(s)); } public static final boolean isNullFileName(String s){ if(s==null || s.equalsIgnoreCase("null") || s.equalsIgnoreCase("none")){return true;} for(int i=0; i int condense(ArrayList list){ if(list==null || list.size()==0){return 0;} int removed=0; for(int i=list.size()-1; i>0; i--){ if(list.get(i)==null){ removed++; X last=list.get(list.size()-1); list.set(i, last); list.remove(list.size()-1); } } return removed; } /** Removes null elements by shrinking the list. Will not change list order. */ public static final int condenseStrict(ArrayList list){ if(list==null || list.size()==0){return 0;} int removed=0; int insertPos=0; for(int i=0; i ArrayList condenseNew(ArrayList list){ ArrayList temp=new ArrayList(list.size()); for(X x : list){ if(x!=null){temp.add(x);} } return temp; } //This should also be correct. I'm not sure which is faster. // /** Removes null elements by shrinking the list. Will not change list order. */ // public static final int condenseStrict(ArrayList list){ // if(list==null || list.size()==0){return 0;} // int removed=0; // int last=0; // // for(int i=0; i ssl, float fractionOfMax, boolean retainPaired){ //// assert(false); // if(ssl==null || ssl.size()==0){return -999999;} // if(ssl.size()==1){return ssl.get(0).score;} // int maxScore=-999999; // for(SiteScore ss : ssl){ // maxScore=Tools.max(maxScore, ss.score); // } // // int cutoff=(int) (maxScore*fractionOfMax); // trimSitesBelowCutoff(ssl, cutoff, retainPaired); //// trimSitesBelowCutoffInplace(ssl, cutoff); // return maxScore; // } /** minSitesToRetain should be set to 1 if the list is not sorted by score (for efficiency of removal). Otherwise, it can be higher. */ public static final int trimSiteList(ArrayList ssl, float fractionOfMax, boolean retainPaired, boolean retainSemiperfect, int minSitesToRetain, int maxSitesToRetain){ // assert(false); if(ssl==null || ssl.size()==0){return -999999;} if(ssl.size()==1){return ssl.get(0).score;} int maxScore=-999999; if(minSitesToRetain>1 && minSitesToRetain ssl, int cutoff, boolean retainPaired, boolean retainSemiperfect, int minSitesToRetain, int maxSitesToRetain){ // assert(false); if(ssl==null || ssl.size()==0){return;} if(ssl.size()==1){return;} trimSitesBelowCutoff(ssl, cutoff, retainPaired, retainSemiperfect, minSitesToRetain, maxSitesToRetain); } public static final > boolean inOrder(ArrayList list){ if(list==null || list.size()<2){return true;} for(int i=1; i0){return false;} } return true; } public static final int mergeDuplicateSites(ArrayList list, boolean doAssertions, boolean mergeDifferentGaps){ if(list==null || list.size()<2){return 0;} Collections.sort(list, SiteScore.PCOMP); int removed=0; SiteScore a=list.get(0); for(int i=1; ib.score || a.slowScore>b.slowScore)))){ throw new RuntimeException("\n"+SiteScore.header()+"\n"+a.toText()+"\n"+b.toText()+"\n"); } assert(a.perfect==b.perfect || (a.perfect && (a.score>b.score || a.slowScore>b.slowScore))) : "\n"+SiteScore.header()+"\n"+a.toText()+"\n"+b.toText()+"\n"; } a.score=max(a.score, b.score); a.slowScore=max(a.slowScore, b.slowScore); a.pairedScore=max(a.pairedScore, b.pairedScore); a.perfect=(a.perfect || b.perfect); if(a.pairedScore>0 && a.pairedScore<=a.score){a.pairedScore=a.score+1;} removed++; list.set(i, null); }else if(mergeDifferentGaps && a.positionalMatch(b, false)){ //Same outermost boundaries, different gaps SiteScore better=null; if(a.score!=b.score){ better=(a.score>b.score ? a : b); }else if(a.slowScore!=b.slowScore){ better=(a.slowScore>b.slowScore ? a : b); }else if(a.pairedScore!=b.pairedScore){ better=(a.pairedScore>b.pairedScore ? a : b); }else{ better=a; } a.score=max(a.score, b.score); a.slowScore=max(a.slowScore, b.slowScore); a.pairedScore=max(a.pairedScore, b.pairedScore); a.perfect=(a.perfect || b.perfect); if(a.pairedScore>0 && a.pairedScore<=a.score){a.pairedScore=a.score+1;} a.gaps=better.gaps; removed++; list.set(i, null); } else{ a=b; } } // if(removed>0){condense(list);} if(removed>0){condenseStrict(list);} return removed; } public static final int subsumeOverlappingSites(ArrayList list, boolean subsumeIfOnlyStartMatches, boolean subsumeInexact){ if(list==null || list.size()<2){return 0;} Collections.sort(list, SiteScore.PCOMP); int removed=0; for(int i=0; ia.start); if(overlappingA && a.strand==b.strand){ SiteScore better=null; if(a.perfect!=b.perfect){ better=a.perfect ? a : b; }if(a.semiperfect!=b.semiperfect){ better=a.semiperfect ? a : b; }else if(a.score!=b.score){ better=(a.score>b.score ? a : b); }else if(a.slowScore!=b.slowScore){ better=(a.slowScore>b.slowScore ? a : b); }else if(a.pairedScore!=b.pairedScore){ better=(a.pairedScore>b.pairedScore ? a : b); }else if(a.pairedScore!=b.pairedScore){ better=(a.quickScore>b.quickScore ? a : b); }else{ better=a; } // if((a.perfect && b.perfect) || (a.semiperfect && b.semiperfect)){ if(a.semiperfect && b.semiperfect){ if(a.start==b.start || a.stop==b.stop){ list.set(i, better); list.set(j, null); removed++; a=better; }else{ //retain both of them } }else if(a.perfect || b.perfect){ list.set(i, better); list.set(j, null); removed++; a=better; }else if(a.semiperfect || b.semiperfect){ if(a.start==b.start && a.stop==b.stop){ list.set(i, better); list.set(j, null); removed++; a=better; }else{ //retain both of them } }else if(subsumeInexact || (a.start==b.start && (subsumeIfOnlyStartMatches || a.stop==b.stop))){ assert(!a.semiperfect && !a.perfect && !b.semiperfect && !b.perfect); a.start=min(a.start, b.start); a.stop=max(a.stop, b.stop); a.score=max(a.score, b.score); a.slowScore=max(a.slowScore, b.slowScore); a.pairedScore=max(a.pairedScore, b.pairedScore); a.quickScore=max(a.quickScore, b.quickScore); if(a.pairedScore>0 && a.pairedScore<=a.score){a.pairedScore=a.score+1;} a.gaps=better.gaps;//Warning! Merging gaps would be better; this could cause out-of-bounds. //TODO: Test for a subsumption length limit. list.set(j, null); removed++; } } } } } } // if(removed>0){condense(list);} if(removed>0){condenseStrict(list);} return removed; } public static final int removeOverlappingSites(ArrayList list, boolean requireAMatchingEnd){ if(list==null || list.size()<2){return 0;} Collections.sort(list, SiteScore.PCOMP); int removed=0; for(int i=0; ia.start); if(overlappingA && a.strand==b.strand){ SiteScore better=null; if(a.perfect!=b.perfect){ better=a.perfect ? a : b; }else if(a.score!=b.score){ better=(a.score>b.score ? a : b); }else if(a.slowScore!=b.slowScore){ better=(a.slowScore>b.slowScore ? a : b); }else if(a.pairedScore!=b.pairedScore){ better=(a.pairedScore>b.pairedScore ? a : b); }else if(a.pairedScore!=b.pairedScore){ better=(a.quickScore>b.quickScore ? a : b); }else{ better=a; } if(a.start==b.start && a.stop==b.stop){ list.set(i, better); list.set(j, null); a=better; removed++; }else if(a.start==b.start || a.stop==b.stop){ //In this case they cannot both be perfect list.set(i, better); list.set(j, null); a=better; removed++; }else if(!requireAMatchingEnd && a.score!=b.score){ list.set(i, better); list.set(j, null); a=better; removed++; } } } } } } // if(removed>0){condense(list);} if(removed>0){condenseStrict(list);} return removed; } /** Returns the number of sitescores in the list within "thresh" of the top score. Assumes list is sorted descending. * This is used to determine whether a mapping is ambiguous. */ public static final int countTopScores(ArrayList list, int thresh){ assert(thresh>=0) : thresh; if(list==null || list.isEmpty()){return 0;} int count=1; final SiteScore ss=list.get(0); final int limit=ss.score-thresh; for(int i=1; i list, int maxSwScore, float multSingle, float multPaired){ if(list==null || list.size()==0){return 0;} assert(multSingle>=multPaired); int initialSize=list.size(); final int swScoreThresh=(int)(maxSwScore*multSingle); //Change low-quality alignments to no-hits. final int swScoreThreshPaired=(int)(maxSwScore*multPaired); if(list.get(0).score=0; i--){ SiteScore ss=list.get(i); assert(ss.score==ss.slowScore); assert(i==0 || ss.slowScore<=list.get(i-1).slowScore) : "List is not sorted by singleton score!"; if(ss.pairedScore>0){ assert(ss.pairedScore>ss.quickScore || ss.pairedScore>ss.slowScore) : ss; if(ss.slowScore list, int maxSwScore, float multSingle){ // if(list==null || list.size()==0){return 0;} // // int initialSize=list.size(); // final int swScoreThresh=(int)(maxSwScore*multSingle); //Change low-quality alignments to no-hits. // if(list.get(0).score=0; i--){ // for(int i=list.size()-1; i>1; i--){ // SiteScore ss=list.get(i); // assert(ss.score==ss.slowScore); // assert(i==0 || ss.slowScore<=list.get(i-1).slowScore) : "List is not sorted by singleton score!"; // assert(ss.pairedScore==0) : ss.toText(); // if(ss.slowScore list, int thresh){ if(list==null || list.size()==0){return 0;} int initialSize=list.size(); if(list.get(0).score=0; i--){ for(int i=list.size()-1; i>1; i--){ SiteScore ss=list.get(i); assert(ss.score==ss.slowScore); assert(i==0 || ss.slowScore<=list.get(i-1).slowScore) : "List is not sorted by singleton score!"; assert(ss.pairedScore==0) : ss.toText(); if(ss.slowScore list, int maxSwScore, float multSingle, float multPaired, int expectedSites){ if(list==null || list.size()==0){return 0;} assert(multSingle>=multPaired); int initialSize=list.size(); final int swScoreThresh=(int)(maxSwScore*multSingle); //Change low-quality alignments to no-hits. final int swScoreThreshPaired=(int)(maxSwScore*multPaired); final int swScoreThresh2=(int)(maxSwScore*multSingle*1.2f); final int swScoreThreshPaired2=(int)(maxSwScore*multPaired*1.1f); if(list.get(0).scoremin; i--){ if(list.get(i).slowScore>=nthBest){break;} list.remove(i); } for(int i=list.size()-1; i>=0; i--){ SiteScore ss=list.get(i); assert(ss.score==ss.slowScore); assert(i==0 || ss.slowScore<=list.get(i-1).slowScore) : "List is not sorted by singleton score!"; if(ss.pairedScore>0){ int thresh=(i>=expectedSites ? swScoreThreshPaired2 : swScoreThreshPaired); assert(ss.pairedScore>ss.quickScore || ss.pairedScore>ss.slowScore) : ss; if(ss.slowScore=expectedSites ? swScoreThresh2 : swScoreThresh); assert(ss.pairedScore==0) : ss.toText(); if(ss.slowScore list, int maxSwScore, float multSingle, int expectedSites){ if(list==null || list.size()==0){return 0;} for(int i=expectedSites/2; imin; i--){ if(list.get(i).slowScore>=nthBest){break;} list.remove(i); } // for(int i=list.size()-1; i>=0; i--){ for(int i=list.size()-1; i>=1; i--){ SiteScore ss=list.get(i); assert(ss.score==ss.slowScore); assert(i==0 || ss.slowScore<=list.get(i-1).slowScore) : "List is not sorted by singleton score!"; assert(ss.pairedScore==0) : ss.toText(); int thresh=(i>=expectedSites ? swScoreThresh2 : swScoreThresh); if(ss.slowScore ssl, int cutoff, boolean retainPaired){ // trimSitesBelowCutoff(ssl, cutoff, retainPaired, 1); // } // public static final void trimSitesBelowCutoff(ArrayList ssl, int cutoff, boolean retainPaired, int minSitesToRetain){ //// assert(false); // assert(minSitesToRetain>=1); // if(ssl==null || ssl.size() ssl2=new ArrayList(ssl.size()); // for(SiteScore ss : ssl){ // if(ss.score>=cutoff || (retainPaired && ss.pairedScore>0)){ // ssl2.add(ss); // } // } // //// Collections.sort(ssl2); //// System.err.println("Cutoff: "+cutoff); //// for(SiteScore ss : ssl2){ //// System.err.print("("+ss.chrom+", "+ss.score+"), "); //// } //// System.err.println(); // // if(ssl2.size()==ssl.size()){return;} //// System.err.println("cutoff: "+cutoff+",\tsize: "+ssl.size()+" -> "+ssl2.size()); // ssl.clear(); // ssl.addAll(ssl2); // } public static final void trimSitesBelowCutoff(ArrayList ssl, int cutoff, boolean retainPaired, boolean retainSemiperfect, int minSitesToRetain, int maxSitesToRetain){ // assert(false); assert(minSitesToRetain>=1); assert(maxSitesToRetain>minSitesToRetain); if(ssl==null || ssl.size()<=minSitesToRetain){return;} while(ssl.size()>maxSitesToRetain){ssl.remove(ssl.size()-1);} int removed=0; final int maxToRemove=ssl.size()-minSitesToRetain; assert(minSitesToRetain==1 || inOrder(ssl)); if(retainPaired){ for(int i=ssl.size()-1; i>=0; i--){ SiteScore ss=ssl.get(i); if(!retainSemiperfect || !ss.semiperfect){ if(ss.score=maxToRemove){ assert(removed==maxToRemove); break; } } } } }else{ for(int i=ssl.size()-1; i>=0; i--){ SiteScore ss=ssl.get(i); if(!retainSemiperfect || !ss.semiperfect){ if(ss.score=maxToRemove){ assert(removed==maxToRemove); break; } } } } } if(removed>0){ condenseStrict(ssl); } assert(ssl.size()>=minSitesToRetain); } //Messes up order // public static final void trimSitesBelowCutoffInplace(ArrayList ssl, int cutoff, boolean retainPaired){ //// assert(false); // if(ssl==null || ssl.size()<2){return;} // // for(int i=0; i=count[i-1]) : "\n\ncount["+i+"]="+count[i]+"\ncount["+(i-1)+"]="+count[i-1]+"\n"; } int pos=count.length-1; for(int sum=0; pos>1 && summaxLengthToKeep2){data[i]=null;} } } public static int findLimitForHighFreqEntries(int[][] data, float fractionToExclude){ if(fractionToExclude<=0){return Integer.MAX_VALUE;} int[] count=new int[data.length]; long numBases=0; for(int i=0; i=count[i-1]) : "\n\ncount["+i+"]="+count[i]+"\ncount["+(i-1)+"]="+count[i-1]+"\n"; } int pos=count.length-1; for(int sum=0; pos>1 && sum=minLength){ if(isClumpy(array, maxDist, fraction)){ removedSites+=array.length; removedKeys++; data[i]=null; } } } // System.err.println("Removed\t"+removedSites+"\t/ "+total+"\tsites," + // " or "+String.format("%.4f", (removedSites*100f/total))+"%"); // System.err.println("Removed\t"+removedKeys+"\t/ "+data.length+"\tkeys," + // " or "+String.format("%.4f", (removedKeys*100f/data.length))+"%"); } public static HashSet banClumpyEntries(final int[][] data, final int maxDist, final int minLength, final float fraction){ HashSet set=new HashSet(128); long total=0; long removedSites=0; long removedKeys=0; if(maxDist<=0){return set;} for(int i=0; i=minLength){ if(isClumpy(array, maxDist, fraction)){ removedSites+=array.length; removedKeys++; set.add(i); } } } // System.err.println("Banned\t"+removedSites+"\t/ "+total+"\tsites," + // " or "+String.format("%.4f", (removedSites*100f/total))+"%"); // System.err.println("Banned\t"+removedKeys+"\t/ "+data.length+"\tkeys," + // " or "+String.format("%.4f", (removedKeys*100f/data.length))+"%"); return set; } public static final boolean isClumpy(final int[] array, final int maxDist, final float fraction){ if(array==null){return false;} int count=0; for(int i=1; i=(array.length*fraction); } public static int[] makeLengthHistogram(int[][] x, int buckets) { int[] lengths=new int[x.length]; long total=0; for(int i=0; i10000000000000L){ div=1000000000000L; ext="T"; }else if(x>10000000000L){ div=1000000000L; ext="B"; }else if(x>10000000){ div=1000000; ext="M"; }else if(x>100000){ div=1000; ext="K"; } return String.format("%.2f", x/div)+ext; } public static long parseKMG(String b){ char c=Character.toLowerCase(b.charAt(b.length()-1)); if(!Character.isLetter(c) && !b.contains(".")){ return Long.parseLong(b); } long mult=1; if(Character.isLetter(c)){ if(c=='k'){mult=1000;} else if(c=='m'){mult=1000000;} else if(c=='g' || c=='b'){mult=1000000000;} else if(c=='t'){mult=1000000000000L;} else{throw new RuntimeException(b);} b=b.substring(0, b.length()-1); } return ((long)Double.parseDouble(b))*mult; } public static boolean parseBoolean(String s){ if(s==null || s.length()<1){return true;} if(s.length()==1){ char c=Character.toLowerCase(s.charAt(0)); return c=='t' || c=='1'; } if(s.equalsIgnoreCase("null") || s.equalsIgnoreCase("none")){return false;} return Boolean.parseBoolean(s); } public static int parseInt(byte[] array, int a, int b){ assert(b>a); int r=0; final byte z='0'; boolean negative=false; if(array[a]=='-'){negative=true; a++;} for(; a=0) : x+" = "+(char)array[a]+"\narray="+new String(array)+", start="+a+", stop="+b; r=(r*10)+x; } if(negative){r*=-1;} return r; } /** TODO: This (temporarily) uses a lot of memory. Could be reduced by making an array of length max(x) and counting occurrences. */ public static int[] makeLengthHistogram2(int[] x, int buckets, boolean verbose) { int[] lengths=Arrays.copyOf(x, x.length); long total=sum(x); Arrays.sort(lengths); if(verbose){ System.out.println("Length array size:\t"+x.length); System.out.println("Min value: \t"+lengths[0]); System.out.println("Med value: \t"+lengths[lengths.length/2]); System.out.println("Max value: \t"+lengths[lengths.length-1]); System.out.println("Total: \t"+total); } int[] hist=new int[buckets+1]; long sum=0; int ptr=0; for(int i=0; ix.length){ Data.sysout.println("Reverted to old histogram mode."); return makeLengthHistogram2(x, buckets, verbose); } int[] counts=new int[max+1]; long total=0; for(int i=0; i=0){ counts[a]++; total+=a; } } return makeLengthHistogram4(counts, buckets, total, verbose); } /** Uses counts of occurrences of lengths rather than raw lengths */ public static int[] makeLengthHistogram4(int[] counts, int buckets, long total, boolean verbose) { if(total<=0){ total=0; for(int i=1; i=target){ return i; } } return array.length-1; } public static int absdif(int a, int b) { return a>b ? a-b : b-a; } public static float absdif(float a, float b) { return a>b ? a-b : b-a; } public static double absdif(double a, double b) { return a>b ? a-b : b-a; } /** Uses unsigned math */ public static final int absdifUnsigned(int a, int b){ return (a<0 == b<0) ? a>b ? a-b : b-a : Integer.MAX_VALUE; } public static final boolean overlap(int a1, int b1, int a2, int b2){ assert(a1<=b1 && a2<=b2) : a1+", "+b1+", "+a2+", "+b2; return a2<=b1 && b2>=a1; } public static final int overlapLength(int a1, int b1, int a2, int b2){ if(!overlap(a1,b1,a2,b2)){return 0;} if(a1<=a2){ return b1>=b2 ? b2-a2+1 : b1-a2+1; }else{ return b2>=b1 ? b1-a1+1 : b2-a1+1; } } /** Is (a1, b1) within (a2, b2) ? */ public static final boolean isWithin(int a1, int b1, int a2, int b2){ assert(a1<=b1 && a2<=b2) : a1+", "+b1+", "+a2+", "+b2; return a1>=a2 && b1<=b2; } public static final int constrict(int point, int a, int b){ assert(a<=b); return(pointb ? b : point); } public static final int indexOf(byte[] array, byte b){ int i=0; while(i=0 && array[i]!=b){i--;} return i; } public static final int stringLength(long x){ if(x<0){ if(x==Integer.MIN_VALUE){return 11;} return lengthOf(-x)+1; } return lengthOf(x); } public static final int stringLength(int x){ if(x<0){ if(x==Long.MIN_VALUE){return 20;} return lengthOf(-x)+1; } return lengthOf(x); } public static final int lengthOf(int x){ assert(x>=0); int i=1; while(x>ilens[i]){i++;} return i; } public static final int lengthOf(long x){ assert(x>=0); int i=1; while(x>llens[i]){i++;} return i; } public static final int max(int[] array){return array[maxIndex(array)];} public static final int maxIndex(int[] array){ int max=array[0], maxIndex=0; for(int i=1; imax){max=array[i];maxIndex=i;} } return maxIndex; } public static final double standardDeviation(long[] numbers){ if(numbers==null || numbers.length<1){return 0;} long sum=sum(numbers); double avg=sum/(double)numbers.length; double sumdev2=0; for(int i=0; i=0); long[] r=new long[bins]; if(bins==0){return r;} double mult=bins/(double)array.length; for(int i=0; iy ? x : y;} public static final int min(int x, int y, int z){return xy ? (x>z ? x : z) : (y>z ? y : z);} public static final int min(int x, int y, int z, int z2){return min(min(x,y), min(z,z2));} public static final int max(int x, int y, int z, int z2){return max(max(x,y), max(z,z2));} //Median of 3 public static final int mid(int x, int y, int z){return xy ? x : y;} public static final char min(char x, char y){return xy ? x : y;} public static final byte min(byte x, byte y, byte z){return xy ? max(x, z) : max(y, z);} public static final byte min(byte x, byte y, byte z, byte a){return min(min(x, y), min(z, a));} public static final byte max(byte x, byte y, byte z, byte a){return max(max(x, y), max(z, a));} public static final long min(long x, long y){return xy ? x : y;} public static final long min(long x, long y, long z){return xy ? (x>z ? x : z) : (y>z ? y : z);} public static final double min(double x, double y){return xy ? x : y;} public static final float min(float x, float y){return xy ? x : y;} public static final int min(int[] array, int fromIndex, int toIndex){ int min=array[fromIndex]; for(int i=fromIndex+1; i<=toIndex; i++){ min=min(min, array[i]); } return min; } public static final int max(int[] array, int fromIndex, int toIndex){ int max=array[fromIndex]; for(int i=fromIndex+1; i<=toIndex; i++){ max=max(max, array[i]); } return max; } public static int minIndex(int[] array) { if(array==null || array.length<1){return -1;} float min=array[0]; int index=0; for(int i=1; i