View Javadoc

1   /*
2   *   org.galagosearch.eval.stat note:
3   *       This is a copy of the Fmath class provided by Dr. Michael Flanagan:
4   *           http://www.ee.ucl.ac.uk/~mflanaga/java/
5   *
6   *   Class   Fmath
7   *
8   *   USAGE:  Mathematical class that supplements java.lang.Math and contains:
9   *               the main physical constants
10  *               trigonemetric functions absent from java.lang.Math
11  *               some useful additional mathematical functions
12  *               some conversion functions
13  *
14  *   WRITTEN BY: Dr Michael Thomas Flanagan
15  *
16  *   DATE:    June 2002
17  *   AMENDED: 6 January 2006, 12 April 2006, 5 May 2006, 28 July 2006
18  *
19  *   DOCUMENTATION:
20  *   See Michael Thomas Flanagan's Java library on-line web page:
21  *   Fmath.html
22  *
23  *   Copyright (c) July 2006
24  *
25  *   PERMISSION TO COPY:
26  *   Permission to use, copy and modify this software and its documentation for
27  *   NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement
28  *   to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies.
29  *
30  *   Dr Michael Thomas Flanagan makes no representations about the suitability
31  *   or fitness of the software for any or for a particular purpose.
32  *   Michael Thomas Flanagan shall not be liable for any damages suffered
33  *   as a result of using, modifying or distributing this software or its derivatives.
34  *
35  ***************************************************************************************/
36  
37  package org.galagosearch.core.eval.stat;
38  
39  import java.util.Vector;
40  
41  public class Fmath {
42  
43          // PHYSICAL CONSTANTS
44  
45          public static final double N_AVAGADRO = 6.0221419947e23;        /*      mol^-1          */
46          public static final double K_BOLTZMANN = 1.380650324e-23;       /*      J K^-1          */
47          public static final double H_PLANCK = 6.6260687652e-34;         /*      J s             */
48          public static final double H_PLANCK_RED = H_PLANCK/(2*Math.PI); /*      J s             */
49          public static final double C_LIGHT = 2.99792458e8;              /*      m s^-1          */
50          public static final double R_GAS = 8.31447215;                  /*      J K^-1 mol^-1   */
51          public static final double F_FARADAY = 9.6485341539e4;          /*      C mol^-1        */
52          public static final double T_ABS = -273.15;                     /*      Celsius         */
53          public static final double Q_ELECTRON = -1.60217646263e-19;     /*      C               */
54          public static final double M_ELECTRON = 9.1093818872e-31;       /*      kg              */
55          public static final double M_PROTON = 1.6726215813e-27;         /*      kg              */
56          public static final double M_NEUTRON = 1.6749271613e-27;        /*      kg              */
57          public static final double EPSILON_0 = 8.854187817e-12;         /*      F m^-1          */
58          public static final double MU_0 = Math.PI*4e-7;                 /*      H m^-1 (N A^-2) */
59  
60          // MATHEMATICAL CONSTANTS
61          public static final double EULER_CONSTANT_GAMMA = 0.5772156649015627;
62          public static final double PI = Math.PI;                        /*  3.141592653589793D  */
63          public static final double E = Math.E;                          /*  2.718281828459045D  */
64  
65  
66          // METHODS
67  
68  
69          // LOGARITHMS
70          // Log to base 10 of a double number
71          public static double log10(double a){
72              return Math.log(a)/Math.log(10.0D);
73          }
74  
75          // Log to base 10 of a float number
76          public static float log10(float a){
77              return (float) (Math.log((double)a)/Math.log(10.0D));
78          }
79  
80          // Base 10 antilog of a double
81          public static double antilog10(double x){
82              return Math.pow(10.0D, x);
83          }
84  
85          // Base 10 antilog of a float
86          public static float antilog10(float x){
87              return (float)Math.pow(10.0D, (double)x);
88          }
89  
90          // Log to base e of a double number
91          public static double log(double a){
92              return Math.log(a);
93          }
94  
95          // Log to base e of a float number
96          public static float log(float a){
97              return (float)Math.log((double)a);
98          }
99  
100         // Base e antilog of a double
101         public static double antilog(double x){
102             return Math.exp(x);
103         }
104 
105         // Base e antilog of a float
106         public static float antilog(float x){
107             return (float)Math.exp((double)x);
108         }
109 
110         // Log to base 2 of a double number
111         public static double log2(double a){
112             return Math.log(a)/Math.log(2.0D);
113         }
114 
115         // Log to base 2 of a float number
116         public static float log2(float a){
117             return (float) (Math.log((double)a)/Math.log(2.0D));
118         }
119 
120         // Base 2 antilog of a double
121         public static double antilog2(double x){
122             return Math.pow(2.0D, x);
123         }
124 
125         // Base 2 antilog of a float
126         public static float antilog2(float x){
127             return (float)Math.pow(2.0D, (double)x);
128         }
129 
130         // Log to base b of a double number and double base
131         public static double log10(double a, double b){
132             return Math.log(a)/Math.log(b);
133         }
134 
135         // Log to base b of a double number and int base
136         public static double log10(double a, int b){
137             return Math.log(a)/Math.log((double)b);
138         }
139 
140         // Log to base b of a float number and flaot base
141         public static float log10(float a, float b){
142             return (float) (Math.log((double)a)/Math.log((double)b));
143         }
144 
145         // Log to base b of a float number and int base
146         public static float log10(float a, int b){
147             return (float) (Math.log((double)a)/Math.log((double)b));
148         }
149 
150         // Square of a double number
151         public static double square(double a){
152             return a*a;
153         }
154 
155         // Square of a float number
156         public static float square(float a){
157             return a*a;
158         }
159 
160         // Square of an int number
161         public static int square(int a){
162             return a*a;
163         }
164 
165         // factorial of n
166         // argument and return are integer, therefore limited to 0<=n<=12
167         // see below for long and double arguments
168         public static int factorial(int n){
169             if(n<0)throw new IllegalArgumentException("n must be a positive integer");
170             if(n>12)throw new IllegalArgumentException("n must less than 13 to avoid integer overflow\nTry long or double argument");
171             int f = 1;
172             for(int i=1; i<=n; i++)f*=i;
173             return f;
174         }
175 
176         // factorial of n
177         // argument and return are long, therefore limited to 0<=n<=20
178         // see below for double argument
179         public static long factorial(long n){
180             if(n<0)throw new IllegalArgumentException("n must be a positive integer");
181             if(n>20)throw new IllegalArgumentException("n must less than 21 to avoid long integer overflow\nTry double argument");
182             long f = 1;
183             for(int i=1; i<=n; i++)f*=i;
184             return f;
185         }
186 
187         // factorial of n
188         // Argument is of type double but must be, numerically, an integer
189         // factorial returned as double but is, numerically, should be an integer
190         // numerical rounding may makes this an approximation after n = 21
191         public static double factorial(double n){
192             if(n<0 || (n-(int)n)!=0)throw new IllegalArgumentException("\nn must be a positive integer\nIs a Gamma funtion [Fmath.gamma(x)] more appropriate?");
193             double f = 1.0D;
194             int nn = (int)n;
195             for(int i=1; i<=nn; i++)f*=i;
196             return f;
197         }
198 
199         // log to base e of the factorial of n
200         // log[e](factorial) returned as double
201         // numerical rounding may makes this an approximation
202         public static double logFactorial(int n){
203             if(n<0 || (n-(int)n)!=0)throw new IllegalArgumentException("\nn must be a positive integer\nIs a Gamma funtion [Fmath.gamma(x)] more appropriate?");
204             double f = 0.0D;
205             for(int i=2; i<=n; i++)f+=Math.log(i);
206             return f;
207         }
208 
209         // log to base e of the factorial of n
210         // Argument is of type double but must be, numerically, an integer
211         // log[e](factorial) returned as double
212         // numerical rounding may makes this an approximation
213         public static double logFactorial(double n){
214         if(n<0 || (n-(int)n)!=0)throw new IllegalArgumentException("\nn must be a positive integer\nIs a Gamma funtion [Fmath.gamma(x)] more appropriate?");
215             double f = 0.0D;
216             int nn = (int)n;
217             for(int i=2; i<=nn; i++)f+=Math.log(i);
218             return f;
219         }
220 
221         // Maximum of a 1D array of doubles, aa
222         public static double maximum(double[] aa){
223             int n = aa.length;
224             double aamax=aa[0];
225             for(int i=1; i<n; i++){
226                 if(aa[i]>aamax)aamax=aa[i];
227             }
228             return aamax;
229         }
230 
231         // Maximum of a 1D array of floats, aa
232         public static float maximum(float[] aa){
233             int n = aa.length;
234             float aamax=aa[0];
235             for(int i=1; i<n; i++){
236                 if(aa[i]>aamax)aamax=aa[i];
237             }
238             return aamax;
239         }
240 
241         // Maximum of a 1D array of ints, aa
242         public static int maximum(int[] aa){
243             int n = aa.length;
244             int aamax=aa[0];
245             for(int i=1; i<n; i++){
246                 if(aa[i]>aamax)aamax=aa[i];
247             }
248             return aamax;
249         }
250 
251         // Maximum of a 1D array of longs, aa
252         public static long maximum(long[] aa){
253             long n = aa.length;
254             long aamax=aa[0];
255             for(int i=1; i<n; i++){
256                 if(aa[i]>aamax)aamax=aa[i];
257             }
258             return aamax;
259         }
260 
261         // Minimum of a 1D array of doubles, aa
262         public static double minimum(double[] aa){
263             int n = aa.length;
264             double aamin=aa[0];
265             for(int i=1; i<n; i++){
266                 if(aa[i]<aamin)aamin=aa[i];
267             }
268             return aamin;
269         }
270 
271         // Minimum of a 1D array of floats, aa
272         public static float minimum(float[] aa){
273             int n = aa.length;
274             float aamin=aa[0];
275             for(int i=1; i<n; i++){
276                 if(aa[i]<aamin)aamin=aa[i];
277             }
278             return aamin;
279         }
280 
281         // Minimum of a 1D array of ints, aa
282         public static int minimum(int[] aa){
283             int n = aa.length;
284             int aamin=aa[0];
285             for(int i=1; i<n; i++){
286                 if(aa[i]<aamin)aamin=aa[i];
287             }
288             return aamin;
289         }
290 
291         // Minimum of a 1D array of longs, aa
292         public static long minimum(long[] aa){
293             long n = aa.length;
294             long aamin=aa[0];
295             for(int i=1; i<n; i++){
296                 if(aa[i]<aamin)aamin=aa[i];
297             }
298             return aamin;
299         }
300 
301         // Reverse the order of the elements of a 1D array of doubles, aa
302         public static double[] reverseArray(double[] aa){
303             int n = aa.length;
304             double[] bb = new double[n];
305             for(int i=0; i<n; i++){
306                bb[i] = aa[n-1-i];
307             }
308             return bb;
309         }
310 
311         // Reverse the order of the elements of a 1D array of floats, aa
312         public static float[] reverseArray(float[] aa){
313             int n = aa.length;
314             float[] bb = new float[n];
315             for(int i=0; i<n; i++){
316                bb[i] = aa[n-1-i];
317             }
318             return bb;
319         }
320 
321         // Reverse the order of the elements of a 1D array of ints, aa
322         public static int[] reverseArray(int[] aa){
323             int n = aa.length;
324             int[] bb = new int[n];
325             for(int i=0; i<n; i++){
326                bb[i] = aa[n-1-i];
327             }
328             return bb;
329         }
330 
331         // Reverse the order of the elements of a 1D array of longs, aa
332         public static long[] reverseArray(long[] aa){
333             int n = aa.length;
334             long[] bb = new long[n];
335             for(int i=0; i<n; i++){
336                bb[i] = aa[n-1-i];
337             }
338             return bb;
339         }
340 
341         // Reverse the order of the elements of a 1D array of char, aa
342         public static char[] reverseArray(char[] aa){
343             int n = aa.length;
344             char[] bb = new char[n];
345             for(int i=0; i<n; i++){
346                bb[i] = aa[n-1-i];
347             }
348             return bb;
349         }
350 
351         // return absolute values of an array of doubles
352         public static double[] arrayAbs(double[] aa){
353             int n = aa.length;
354             double[] bb = new double[n];
355             for(int i=0; i<n; i++){
356                bb[i] = Math.abs(aa[i]);
357             }
358             return bb;
359         }
360 
361         // return absolute values of an array of floats
362         public static float[] arrayAbs(float[] aa){
363             int n = aa.length;
364             float[] bb = new float[n];
365             for(int i=0; i<n; i++){
366                bb[i] = Math.abs(aa[i]);
367             }
368             return bb;
369         }
370 
371         // return absolute values of an array of long
372         public static long[] arrayAbs(long[] aa){
373             int n = aa.length;
374             long[] bb = new long[n];
375             for(int i=0; i<n; i++){
376                bb[i] = Math.abs(aa[i]);
377             }
378             return bb;
379         }
380 
381         // return absolute values of an array of int
382         public static int[] arrayAbs(int[] aa){
383             int n = aa.length;
384             int[] bb = new int[n];
385             for(int i=0; i<n; i++){
386                bb[i] = Math.abs(aa[i]);
387             }
388             return bb;
389         }
390 
391         // multiple all elements by a constant double[] by double -> double[]
392         public static double[] arrayMultByConstant(double[] aa, double constant){
393             int n = aa.length;
394             double[] bb = new double[n];
395             for(int i=0; i<n; i++){
396                bb[i] = aa[i]*constant;
397             }
398             return bb;
399         }
400 
401         // multiple all elements by a constant int[] by double -> double[]
402         public static double[] arrayMultByConstant(int[] aa, double constant){
403             int n = aa.length;
404             double[] bb = new double[n];
405             for(int i=0; i<n; i++){
406                bb[i] = (double)aa[i]*constant;
407             }
408             return bb;
409         }
410         // multiple all elements by a constant double[] by int -> double[]
411         public static double[] arrayMultByConstant(double[] aa, int constant){
412             int n = aa.length;
413             double[] bb = new double[n];
414             for(int i=0; i<n; i++){
415                bb[i] = aa[i]*(double)constant;
416             }
417             return bb;
418         }
419 
420         // multiple all elements by a constant int[] by int -> double[]
421         public static double[] arrayMultByConstant(int[] aa, int constant){
422             int n = aa.length;
423             double[] bb = new double[n];
424             for(int i=0; i<n; i++){
425                bb[i] = (double)(aa[i]*constant);
426             }
427             return bb;
428         }
429 
430         // finds the value of nearest element value in array to the argument value
431         public static double nearestElementValue(double[] array, double value){
432             double diff = Math.abs(array[0] - value);
433             double nearest = array[0];
434             for(int i=1; i<array.length; i++){
435                 if(Math.abs(array[i] - value)<diff){
436                     diff = Math.abs(array[i] - value);
437                     nearest = array[i];
438                 }
439             }
440             return nearest;
441         }
442 
443         // finds the index of nearest element value in array to the argument value
444         public static int nearestElementIndex(double[] array, double value){
445             double diff = Math.abs(array[0] - value);
446             int nearest = 0;
447             for(int i=1; i<array.length; i++){
448                 if(Math.abs(array[i] - value)<diff){
449                     diff = Math.abs(array[i] - value);
450                     nearest = i;
451                 }
452             }
453             return nearest;
454         }
455 
456         // finds the value of nearest lower element value in array to the argument value
457         public static double nearestLowerElementValue(double[] array, double value){
458             double diff0 = 0.0D;
459             double diff1 = 0.0D;
460             double nearest = 0.0D;
461             int ii = 0;
462             boolean test = true;
463             double min = array[0];
464             while(test){
465                 if(array[ii]<min)min = array[ii];
466                 if((value - array[ii])>=0.0D){
467                     diff0 = value - array[ii];
468                     nearest = array[ii];
469                     test = false;
470                 }
471                 else{
472                     ii++;
473                     if(ii>array.length-1){
474                         nearest = min;
475                         diff0 = min - value;
476                         test = false;
477                     }
478                 }
479             }
480             for(int i=0; i<array.length; i++){
481                 diff1 = value - array[i];
482                 if(diff1>=0.0D && diff1<diff0 ){
483                     diff0 = diff1;
484                     nearest = array[i];
485                 }
486             }
487             return nearest;
488         }
489 
490         // finds the index of nearest lower element value in array to the argument value
491         public static int nearestLowerElementIndex(double[] array, double value){
492             double diff0 = 0.0D;
493             double diff1 = 0.0D;
494             int nearest = 0;
495             int ii = 0;
496             boolean test = true;
497             double min = array[0];
498             int minI = 0;
499             while(test){
500                 if(array[ii]<min){
501                     min = array[ii];
502                     minI = ii;
503                 }
504                 if((value - array[ii])>=0.0D){
505                     diff0 = value - array[ii];
506                     nearest = ii;
507                     test = false;
508                 }
509                 else{
510                     ii++;
511                     if(ii>array.length-1){
512                         nearest = minI;
513                         diff0 = min - value;
514                         test = false;
515                     }
516                 }
517             }
518             for(int i=0; i<array.length; i++){
519                 diff1 = value - array[i];
520                 if(diff1>=0.0D && diff1<diff0 ){
521                     diff0 = diff1;
522                     nearest = i;
523                 }
524             }
525             return nearest;
526         }
527 
528         // finds the value of nearest higher element value in array to the argument value
529         public static double nearestHigherElementValue(double[] array, double value){
530             double diff0 = 0.0D;
531             double diff1 = 0.0D;
532             double nearest = 0.0D;
533             int ii = 0;
534             boolean test = true;
535             double max = array[0];
536             while(test){
537                 if(array[ii]>max)max = array[ii];
538                 if((array[ii] - value )>=0.0D){
539                     diff0 = value - array[ii];
540                     nearest = array[ii];
541                     test = false;
542                 }
543                 else{
544                     ii++;
545                     if(ii>array.length-1){
546                         nearest = max;
547                         diff0 = value - max;
548                         test = false;
549                     }
550                 }
551             }
552             for(int i=0; i<array.length; i++){
553                 diff1 = array[i]- value;
554                 if(diff1>=0.0D && diff1<diff0 ){
555                     diff0 = diff1;
556                     nearest = array[i];
557                 }
558             }
559             return nearest;
560         }
561 
562         // finds the index of nearest higher element value in array to the argument value
563         public static int nearestHigherElementIndex(double[] array, double value){
564             double diff0 = 0.0D;
565             double diff1 = 0.0D;
566             int nearest = 0;
567             int ii = 0;
568             boolean test = true;
569             double max = array[0];
570             int maxI = 0;
571             while(test){
572                 if(array[ii]>max){
573                     max = array[ii];
574                     maxI = ii;
575                 }
576                 if((array[ii] - value )>=0.0D){
577                     diff0 = value - array[ii];
578                     nearest = ii;
579                     test = false;
580                 }
581                 else{
582                     ii++;
583                     if(ii>array.length-1){
584                         nearest = maxI;
585                         diff0 = value - max;
586                         test = false;
587                     }
588                 }
589             }
590             for(int i=0; i<array.length; i++){
591                 diff1 = array[i]- value;
592                 if(diff1>=0.0D && diff1<diff0 ){
593                     diff0 = diff1;
594                     nearest = i;
595                 }
596             }
597             return nearest;
598         }
599 
600 
601         // finds the value of nearest element value in array to the argument value
602         public static int nearestElementValue(int[] array, int value){
603             int diff = (int) Math.abs(array[0] - value);
604             int nearest = array[0];
605             for(int i=1; i<array.length; i++){
606                if((int) Math.abs(array[i] - value)<diff){
607                     diff = (int)Math.abs(array[i] - value);
608                     nearest = array[i];
609                 }
610             }
611             return nearest;
612         }
613 
614         // finds the index of nearest element value in array to the argument value
615         public static int nearestElementIndex(int[] array, int value){
616             int diff = (int) Math.abs(array[0] - value);
617             int nearest = 0;
618             for(int i=1; i<array.length; i++){
619                 if((int) Math.abs(array[i] - value)<diff){
620                     diff = (int)Math.abs(array[i] - value);
621                     nearest = i;
622                 }
623             }
624             return nearest;
625         }
626 
627         // finds the value of nearest lower element value in array to the argument value
628         public static int nearestLowerElementValue(int[] array, int value){
629             int diff0 = 0;
630             int diff1 = 0;
631             int nearest = 0;
632             int ii = 0;
633             boolean test = true;
634             int min = array[0];
635             while(test){
636                 if(array[ii]<min)min = array[ii];
637                 if((value - array[ii])>=0){
638                     diff0 = value - array[ii];
639                     nearest = array[ii];
640                     test = false;
641                 }
642                 else{
643                     ii++;
644                     if(ii>array.length-1){
645                         nearest = min;
646                         diff0 = min - value;
647                         test = false;
648                     }
649                 }
650             }
651             for(int i=0; i<array.length; i++){
652                 diff1 = value - array[i];
653                 if(diff1>=0 && diff1<diff0 ){
654                     diff0 = diff1;
655                     nearest = array[i];
656                 }
657             }
658             return nearest;
659         }
660 
661         // finds the index of nearest lower element value in array to the argument value
662         public static int nearestLowerElementIndex(int[] array, int value){
663             int diff0 = 0;
664             int diff1 = 0;
665             int nearest = 0;
666             int ii = 0;
667             boolean test = true;
668             int min = array[0];
669             int minI = 0;
670             while(test){
671                 if(array[ii]<min){
672                     min = array[ii];
673                     minI = ii;
674                 }
675                 if((value - array[ii])>=0){
676                     diff0 = value - array[ii];
677                     nearest = ii;
678                     test = false;
679                 }
680                 else{
681                     ii++;
682                     if(ii>array.length-1){
683                         nearest = minI;
684                         diff0 = min - value;
685                         test = false;
686                     }
687                 }
688             }
689             for(int i=0; i<array.length; i++){
690                 diff1 = value - array[i];
691                 if(diff1>=0 && diff1<diff0 ){
692                     diff0 = diff1;
693                     nearest = i;
694                 }
695             }
696             return nearest;
697         }
698 
699         // finds the value of nearest higher element value in array to the argument value
700         public static int nearestHigherElementValue(int[] array, int value){
701             int diff0 = 0;
702             int diff1 = 0;
703             int nearest = 0;
704             int ii = 0;
705             boolean test = true;
706             int max = array[0];
707             while(test){
708                 if(array[ii]>max)max = array[ii];
709                 if((array[ii] - value )>=0){
710                     diff0 = value - array[ii];
711                     nearest = array[ii];
712                     test = false;
713                 }
714                 else{
715                     ii++;
716                     if(ii>array.length-1){
717                         nearest = max;
718                         diff0 = value - max;
719                         test = false;
720                     }
721                 }
722             }
723             for(int i=0; i<array.length; i++){
724                 diff1 = array[i]- value;
725                 if(diff1>=0 && diff1<diff0 ){
726                     diff0 = diff1;
727                     nearest = array[i];
728                 }
729             }
730             return nearest;
731         }
732 
733         // finds the index of nearest higher element value in array to the argument value
734         public static int nearestHigherElementIndex(int[] array, int value){
735             int diff0 = 0;
736             int diff1 = 0;
737             int nearest = 0;
738             int ii = 0;
739             boolean test = true;
740             int max = array[0];
741             int maxI = 0;
742             while(test){
743                 if(array[ii]>max){
744                     max = array[ii];
745                     maxI = ii;
746                 }
747                 if((array[ii] - value )>=0){
748                     diff0 = value - array[ii];
749                     nearest = ii;
750                     test = false;
751                 }
752                 else{
753                     ii++;
754                     if(ii>array.length-1){
755                         nearest = maxI;
756                         diff0 = value - max;
757                         test = false;
758                     }
759                 }
760             }
761             for(int i=0; i<array.length; i++){
762                 diff1 = array[i]- value;
763                 if(diff1>=0 && diff1<diff0 ){
764                     diff0 = diff1;
765                     nearest = i;
766                 }
767             }
768             return nearest;
769         }
770 
771         // Sum of all array elements - double array
772         public static double arraySum(double[]array){
773             double sum = 0.0D;
774             for(double i:array)sum += i;
775             return sum;
776         }
777 
778         // Sum of all array elements - float array
779         public static float arraySum(float[]array){
780             float sum = 0.0F;
781             for(float i:array)sum += i;
782             return sum;
783         }
784 
785         // Sum of all array elements - int array
786         public static int arraySum(int[]array){
787             int sum = 0;
788             for(int i:array)sum += i;
789             return sum;
790         }
791 
792         // Sum of all array elements - long array
793         public static long arraySum(long[]array){
794             long sum = 0L;
795             for(long i:array)sum += i;
796             return sum;
797         }
798 
799         // Product of all array elements - double array
800         public static double arrayProduct(double[]array){
801             double product = 1.0D;
802             for(double i:array)product *= i;
803             return product;
804         }
805 
806         // Product of all array elements - float array
807         public static float arrayProduct(float[]array){
808             float product = 1.0F;
809             for(float i:array)product *= i;
810             return product;
811         }
812 
813         // Product of all array elements - int array
814         public static int arrayProduct(int[]array){
815             int product = 1;
816             for(int i:array)product *= i;
817             return product;
818         }
819 
820         // Product of all array elements - long array
821         public static long arrayProduct(long[]array){
822             long product = 1L;
823             for(long i:array)product *= i;
824             return product;
825         }
826 
827         // Concatenate two double arrays
828         public static double[] concatenate(double[] aa, double[] bb){
829             int aLen = aa.length;
830             int bLen = bb.length;
831             int cLen = aLen + bLen;
832             double[] cc = new double[cLen];
833             for(int i=0; i<aLen; i++)cc[i] = aa[i];
834             for(int i=0; i<bLen; i++)cc[i+aLen] = bb[i];
835 
836             return cc;
837         }
838 
839         // Concatenate two float arrays
840         public static float[] concatenate(float[] aa, float[] bb){
841             int aLen = aa.length;
842             int bLen = bb.length;
843             int cLen = aLen + bLen;
844             float[] cc = new float[cLen];
845             for(int i=0; i<aLen; i++)cc[i] = aa[i];
846             for(int i=0; i<bLen; i++)cc[i+aLen] = bb[i];
847 
848             return cc;
849         }
850 
851         // Concatenate two int arrays
852         public static int[] concatenate(int[] aa, int[] bb){
853             int aLen = aa.length;
854             int bLen = bb.length;
855             int cLen = aLen + bLen;
856             int[] cc = new int[cLen];
857             for(int i=0; i<aLen; i++)cc[i] = aa[i];
858             for(int i=0; i<bLen; i++)cc[i+aLen] = bb[i];
859 
860             return cc;
861         }
862 
863         // Concatenate two long arrays
864         public static long[] concatenate(long[] aa, long[] bb){
865             int aLen = aa.length;
866             int bLen = bb.length;
867             int cLen = aLen + bLen;
868             long[] cc = new long[cLen];
869             for(int i=0; i<aLen; i++)cc[i] = aa[i];
870             for(int i=0; i<bLen; i++)cc[i+aLen] = bb[i];
871 
872             return cc;
873         }
874 
875         // recast an array of float as doubles
876         public static double[] floatTOdouble(float[] aa){
877             int n = aa.length;
878             double[] bb = new double[n];
879             for(int i=0; i<n; i++){
880                bb[i] = (double)aa[i];
881             }
882             return bb;
883         }
884 
885         // recast an array of int as double
886         public static double[] intTOdouble(int[] aa){
887             int n = aa.length;
888             double[] bb = new double[n];
889             for(int i=0; i<n; i++){
890                bb[i] = (double)aa[i];
891             }
892             return bb;
893         }
894 
895         // recast an array of int as float
896         public static float[] intTOfloat(int[] aa){
897             int n = aa.length;
898             float[] bb = new float[n];
899             for(int i=0; i<n; i++){
900                bb[i] = (float)aa[i];
901             }
902             return bb;
903         }
904 
905         // recast an array of int as long
906         public static long[] intTOlong(int[] aa){
907             int n = aa.length;
908             long[] bb = new long[n];
909             for(int i=0; i<n; i++){
910                bb[i] = (long)aa[i];
911             }
912             return bb;
913         }
914 
915         // recast an array of long as double
916         // BEWARE POSSIBLE LOSS OF PRECISION
917         public static double[] longTOdouble(long[] aa){
918             int n = aa.length;
919             double[] bb = new double[n];
920             for(int i=0; i<n; i++){
921                bb[i] = (double)aa[i];
922             }
923             return bb;
924         }
925 
926         // recast an array of long as float
927         // BEWARE POSSIBLE LOSS OF PRECISION
928         public static float[] longTOfloat(long[] aa){
929             int n = aa.length;
930             float[] bb = new float[n];
931             for(int i=0; i<n; i++){
932                bb[i] = (float)aa[i];
933             }
934             return bb;
935         }
936 
937         // recast an array of short as double
938         public static double[] shortTOdouble(short[] aa){
939             int n = aa.length;
940             double[] bb = new double[n];
941             for(int i=0; i<n; i++){
942                bb[i] = (double)aa[i];
943             }
944             return bb;
945         }
946 
947          // recast an array of short as float
948         public static float[] shortTOfloat(short[] aa){
949             int n = aa.length;
950             float[] bb = new float[n];
951             for(int i=0; i<n; i++){
952                bb[i] = (float)aa[i];
953             }
954             return bb;
955         }
956 
957         // recast an array of short as long
958         public static long[] shortTOlong(short[] aa){
959             int n = aa.length;
960             long[] bb = new long[n];
961             for(int i=0; i<n; i++){
962                bb[i] = (long)aa[i];
963             }
964             return bb;
965         }
966 
967         // recast an array of short as int
968         public static int[] shortTOint(short[] aa){
969             int n = aa.length;
970             int[] bb = new int[n];
971             for(int i=0; i<n; i++){
972                bb[i] = (int)aa[i];
973             }
974             return bb;
975         }
976 
977         // recast an array of byte as double
978         public static double[] byteTOdouble(byte[] aa){
979             int n = aa.length;
980             double[] bb = new double[n];
981             for(int i=0; i<n; i++){
982                bb[i] = (int)aa[i];
983             }
984             return bb;
985         }
986 
987         // recast an array of byte as float
988         public static float[] byteTOfloat(byte[] aa){
989             int n = aa.length;
990             float[] bb = new float[n];
991             for(int i=0; i<n; i++){
992                bb[i] = (float)aa[i];
993             }
994             return bb;
995         }
996 
997         // recast an array of byte as long
998         public static long[] byteTOlong(byte[] aa){
999             int n = aa.length;
1000             long[] bb = new long[n];
1001             for(int i=0; i<n; i++){
1002                bb[i] = (long)aa[i];
1003             }
1004             return bb;
1005         }
1006 
1007         // recast an array of byte as int
1008         public static int[] byteTOint(byte[] aa){
1009             int n = aa.length;
1010             int[] bb = new int[n];
1011             for(int i=0; i<n; i++){
1012                bb[i] = (int)aa[i];
1013             }
1014             return bb;
1015         }
1016 
1017         // recast an array of byte as short
1018         public static short[] byteTOshort(byte[] aa){
1019             int n = aa.length;
1020             short[] bb = new short[n];
1021             for(int i=0; i<n; i++){
1022                bb[i] = (short)aa[i];
1023             }
1024             return bb;
1025         }
1026 
1027         // recast an array of double as int
1028         // BEWARE OF LOSS OF PRECISION
1029         public static int[] doubleTOint(double[] aa){
1030             int n = aa.length;
1031             int[] bb = new int[n];
1032             for(int i=0; i<n; i++){
1033                bb[i] = (int)aa[i];
1034             }
1035             return bb;
1036         }
1037 
1038         // print an array of doubles to screen
1039         // No line returns except at the end
1040         public static void print(double[] aa){
1041             for(int i=0; i<aa.length; i++){
1042                 System.out.print(aa[i]+"   ");
1043             }
1044             System.out.println();
1045         }
1046 
1047         // print an array of doubles to screen
1048         // with line returns
1049         public static void println(double[] aa){
1050             for(int i=0; i<aa.length; i++){
1051                 System.out.println(aa[i]+"   ");
1052             }
1053         }
1054 
1055         // print an array of floats to screen
1056         // No line returns except at the end
1057         public static void print(float[] aa){
1058             for(int i=0; i<aa.length; i++){
1059                 System.out.print(aa[i]+"   ");
1060             }
1061             System.out.println();
1062         }
1063 
1064         // print an array of floats to screen
1065         // with line returns
1066         public static void println(float[] aa){
1067             for(int i=0; i<aa.length; i++){
1068                 System.out.println(aa[i]+"   ");
1069             }
1070         }
1071 
1072         // print an array of ints to screen
1073         // No line returns except at the end
1074         public static void print(int[] aa){
1075             for(int i=0; i<aa.length; i++){
1076                 System.out.print(aa[i]+"   ");
1077             }
1078             System.out.println();
1079         }
1080 
1081         // print an array of ints to screen
1082         // with line returns
1083         public static void println(int[] aa){
1084             for(int i=0; i<aa.length; i++){
1085                 System.out.println(aa[i]+"   ");
1086             }
1087         }
1088 
1089         // print an array of longs to screen
1090         // No line returns except at the end
1091         public static void print(long[] aa){
1092             for(int i=0; i<aa.length; i++){
1093                 System.out.print(aa[i]+"   ");
1094             }
1095             System.out.println();
1096         }
1097 
1098         // print an array of longs to screen
1099         // with line returns
1100         public static void println(long[] aa){
1101             for(int i=0; i<aa.length; i++){
1102                 System.out.println(aa[i]+"   ");
1103             }
1104         }
1105 
1106         // print an array of char to screen
1107         // No line returns except at the end
1108         public static void print(char[] aa){
1109             for(int i=0; i<aa.length; i++){
1110                 System.out.print(aa[i]+"   ");
1111             }
1112             System.out.println();
1113         }
1114 
1115         // print an array of char to screen
1116         // with line returns
1117         public static void println(char[] aa){
1118             for(int i=0; i<aa.length; i++){
1119                 System.out.println(aa[i]+"   ");
1120             }
1121         }
1122 
1123         // print an array of String to screen
1124         // No line returns except at the end
1125         public static void print(String[] aa){
1126             for(int i=0; i<aa.length; i++){
1127                 System.out.print(aa[i]+"   ");
1128             }
1129             System.out.println();
1130         }
1131 
1132         // print an array of Strings to screen
1133         // with line returns
1134         public static void println(String[] aa){
1135             for(int i=0; i<aa.length; i++){
1136                 System.out.println(aa[i]+"   ");
1137             }
1138         }
1139 
1140         // sort elements in an array of doubles into ascending order
1141         // using selection sort method
1142         // returns Vector containing the original array, the sorted array
1143         //  and an array of the indices of the sorted array
1144         public static Vector<Object> selectSortVector(double[] aa){
1145             int index = 0;
1146             int lastIndex = -1;
1147             int n = aa.length;
1148             double holdb = 0.0D;
1149             int holdi = 0;
1150             double[] bb = new double[n];
1151             int[] indices = new int[n];
1152             for(int i=0; i<n; i++){
1153                 bb[i]=aa[i];
1154                 indices[i]=i;
1155             }
1156 
1157             while(lastIndex != n-1){
1158                 index = lastIndex+1;
1159                 for(int i=lastIndex+2; i<n; i++){
1160                     if(bb[i]<bb[index]){
1161                         index=i;
1162                     }
1163                 }
1164                 lastIndex++;
1165                 holdb=bb[index];
1166                 bb[index]=bb[lastIndex];
1167                 bb[lastIndex]=holdb;
1168                 holdi=indices[index];
1169                 indices[index]=indices[lastIndex];
1170                 indices[lastIndex]=holdi;
1171             }
1172             Vector<Object> vec = new Vector<Object>();
1173             vec.addElement(aa);
1174             vec.addElement(bb);
1175             vec.addElement(indices);
1176             return vec;
1177         }
1178 
1179         // sort elements in an array of doubles into ascending order
1180         // using selection sort method
1181         public static double[] selectionSort(double[] aa){
1182             int index = 0;
1183             int lastIndex = -1;
1184             int n = aa.length;
1185             double hold = 0.0D;
1186             double[] bb = new double[n];
1187             for(int i=0; i<n; i++){
1188                 bb[i]=aa[i];
1189             }
1190 
1191             while(lastIndex != n-1){
1192                 index = lastIndex+1;
1193                 for(int i=lastIndex+2; i<n; i++){
1194                     if(bb[i]<bb[index]){
1195                         index=i;
1196                     }
1197                 }
1198                 lastIndex++;
1199                 hold=bb[index];
1200                 bb[index]=bb[lastIndex];
1201                 bb[lastIndex]=hold;
1202             }
1203             return bb;
1204         }
1205 
1206         // sort elements in an array of floats into ascending order
1207         // using selection sort method
1208         public static float[] selectionSort(float[] aa){
1209             int index = 0;
1210             int lastIndex = -1;
1211             int n = aa.length;
1212             float hold = 0.0F;
1213             float[] bb = new float[n];
1214             for(int i=0; i<n; i++){
1215                 bb[i]=aa[i];
1216             }
1217 
1218             while(lastIndex != n-1){
1219                 index = lastIndex+1;
1220                 for(int i=lastIndex+2; i<n; i++){
1221                     if(bb[i]<bb[index]){
1222                         index=i;
1223                     }
1224                 }
1225                 lastIndex++;
1226                 hold=bb[index];
1227                 bb[index]=bb[lastIndex];
1228                 bb[lastIndex]=hold;
1229             }
1230             return bb;
1231         }
1232 
1233         // sort elements in an array of ints into ascending order
1234         // using selection sort method
1235         public static int[] selectionSort(int[] aa){
1236             int index = 0;
1237             int lastIndex = -1;
1238             int n = aa.length;
1239             int hold = 0;
1240             int[] bb = new int[n];
1241             for(int i=0; i<n; i++){
1242                 bb[i]=aa[i];
1243             }
1244 
1245             while(lastIndex != n-1){
1246                 index = lastIndex+1;
1247                 for(int i=lastIndex+2; i<n; i++){
1248                     if(bb[i]<bb[index]){
1249                         index=i;
1250                     }
1251                 }
1252                 lastIndex++;
1253                 hold=bb[index];
1254                 bb[index]=bb[lastIndex];
1255                 bb[lastIndex]=hold;
1256             }
1257             return bb;
1258         }
1259 
1260         // sort elements in an array of longs into ascending order
1261         // using selection sort method
1262         public static long[] selectionSort(long[] aa){
1263             int index = 0;
1264             int lastIndex = -1;
1265             int n = aa.length;
1266             long hold = 0L;
1267             long[] bb = new long[n];
1268             for(int i=0; i<n; i++){
1269                 bb[i]=aa[i];
1270             }
1271 
1272             while(lastIndex != n-1){
1273                 index = lastIndex+1;
1274                 for(int i=lastIndex+2; i<n; i++){
1275                     if(bb[i]<bb[index]){
1276                         index=i;
1277                     }
1278                 }
1279                 lastIndex++;
1280                 hold=bb[index];
1281                 bb[index]=bb[lastIndex];
1282                 bb[lastIndex]=hold;
1283             }
1284             return bb;
1285         }
1286 
1287         // sort elements in an array of doubles into ascending order
1288         // using selection sort method
1289         // returns Vector containing the original array, the sorted array
1290         //  and an array of the indices of the sorted array
1291         public static void selectionSort(double[] aa, double[] bb, int[] indices){
1292             int index = 0;
1293             int lastIndex = -1;
1294             int n = aa.length;
1295             double holdb = 0.0D;
1296             int holdi = 0;
1297             for(int i=0; i<n; i++){
1298                 bb[i]=aa[i];
1299                 indices[i]=i;
1300             }
1301 
1302             while(lastIndex != n-1){
1303                 index = lastIndex+1;
1304                 for(int i=lastIndex+2; i<n; i++){
1305                     if(bb[i]<bb[index]){
1306                         index=i;
1307                     }
1308                 }
1309                 lastIndex++;
1310                 holdb=bb[index];
1311                 bb[index]=bb[lastIndex];
1312                 bb[lastIndex]=holdb;
1313                 holdi=indices[index];
1314                 indices[index]=indices[lastIndex];
1315                 indices[lastIndex]=holdi;
1316             }
1317         }
1318 
1319         // sort the elements of an array into ascending order with matching switches in an array of the length
1320         // using selection sort method
1321         // array determining the order is the first argument
1322         // matching array  is the second argument
1323         // sorted arrays returned as third and fourth arguments resopectively
1324         public static void selectionSort(double[] aa, double[] bb, double[] cc, double[] dd){
1325             int index = 0;
1326             int lastIndex = -1;
1327             int n = aa.length;
1328             int m = bb.length;
1329             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1330             int nn = cc.length;
1331             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1332             int mm = dd.length;
1333             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1334 
1335             double holdx = 0.0D;
1336             double holdy = 0.0D;
1337 
1338 
1339             for(int i=0; i<n; i++){
1340                 cc[i]=aa[i];
1341                 dd[i]=bb[i];
1342             }
1343 
1344             while(lastIndex != n-1){
1345                 index = lastIndex+1;
1346                 for(int i=lastIndex+2; i<n; i++){
1347                     if(cc[i]<cc[index]){
1348                         index=i;
1349                     }
1350                 }
1351                 lastIndex++;
1352                 holdx=cc[index];
1353                 cc[index]=cc[lastIndex];
1354                 cc[lastIndex]=holdx;
1355                 holdy=dd[index];
1356                 dd[index]=dd[lastIndex];
1357                 dd[lastIndex]=holdy;
1358             }
1359        }
1360 
1361         public static void selectionSort(float[] aa, float[] bb, float[] cc, float[] dd){
1362             int index = 0;
1363             int lastIndex = -1;
1364             int n = aa.length;
1365             int m = bb.length;
1366             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1367             int nn = cc.length;
1368             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1369             int mm = dd.length;
1370             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1371 
1372             float holdx = 0.0F;
1373             float holdy = 0.0F;
1374 
1375 
1376             for(int i=0; i<n; i++){
1377                 cc[i]=aa[i];
1378                 dd[i]=bb[i];
1379             }
1380 
1381             while(lastIndex != n-1){
1382                 index = lastIndex+1;
1383                 for(int i=lastIndex+2; i<n; i++){
1384                     if(cc[i]<cc[index]){
1385                         index=i;
1386                     }
1387                 }
1388                 lastIndex++;
1389                 holdx=cc[index];
1390                 cc[index]=cc[lastIndex];
1391                 cc[lastIndex]=holdx;
1392                 holdy=dd[index];
1393                 dd[index]=dd[lastIndex];
1394                 dd[lastIndex]=holdy;
1395             }
1396        }
1397 
1398        public static void selectionSort(long[] aa, long[] bb, long[] cc, long[] dd){
1399             int index = 0;
1400             int lastIndex = -1;
1401             int n = aa.length;
1402             int m = bb.length;
1403             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1404             int nn = cc.length;
1405             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1406             int mm = dd.length;
1407             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1408 
1409             long holdx = 0L;
1410             long holdy = 0L;
1411 
1412 
1413             for(int i=0; i<n; i++){
1414                 cc[i]=aa[i];
1415                 dd[i]=bb[i];
1416             }
1417 
1418             while(lastIndex != n-1){
1419                 index = lastIndex+1;
1420                 for(int i=lastIndex+2; i<n; i++){
1421                     if(cc[i]<cc[index]){
1422                         index=i;
1423                     }
1424                 }
1425                 lastIndex++;
1426                 holdx=cc[index];
1427                 cc[index]=cc[lastIndex];
1428                 cc[lastIndex]=holdx;
1429                 holdy=dd[index];
1430                 dd[index]=dd[lastIndex];
1431                 dd[lastIndex]=holdy;
1432             }
1433        }
1434 
1435        public static void selectionSort(int[] aa, int[] bb, int[] cc, int[] dd){
1436             int index = 0;
1437             int lastIndex = -1;
1438             int n = aa.length;
1439             int m = bb.length;
1440             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1441             int nn = cc.length;
1442             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1443             int mm = dd.length;
1444             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1445 
1446             int holdx = 0;
1447             int holdy = 0;
1448 
1449 
1450             for(int i=0; i<n; i++){
1451                 cc[i]=aa[i];
1452                 dd[i]=bb[i];
1453             }
1454 
1455             while(lastIndex != n-1){
1456                 index = lastIndex+1;
1457                 for(int i=lastIndex+2; i<n; i++){
1458                     if(cc[i]<cc[index]){
1459                         index=i;
1460                     }
1461                 }
1462                 lastIndex++;
1463                 holdx=cc[index];
1464                 cc[index]=cc[lastIndex];
1465                 cc[lastIndex]=holdx;
1466                 holdy=dd[index];
1467                 dd[index]=dd[lastIndex];
1468                 dd[lastIndex]=holdy;
1469             }
1470        }
1471 
1472        public static void selectionSort(double[] aa, long[] bb, double[] cc, long[] dd){
1473             int index = 0;
1474             int lastIndex = -1;
1475             int n = aa.length;
1476             int m = bb.length;
1477             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1478             int nn = cc.length;
1479             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1480             int mm = dd.length;
1481             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1482 
1483             double holdx = 0.0D;
1484             long holdy = 0L;
1485 
1486 
1487             for(int i=0; i<n; i++){
1488                 cc[i]=aa[i];
1489                 dd[i]=bb[i];
1490             }
1491 
1492             while(lastIndex != n-1){
1493                 index = lastIndex+1;
1494                 for(int i=lastIndex+2; i<n; i++){
1495                     if(cc[i]<cc[index]){
1496                         index=i;
1497                     }
1498                 }
1499                 lastIndex++;
1500                 holdx=cc[index];
1501                 cc[index]=cc[lastIndex];
1502                 cc[lastIndex]=holdx;
1503                 holdy=dd[index];
1504                 dd[index]=dd[lastIndex];
1505                 dd[lastIndex]=holdy;
1506             }
1507        }
1508 
1509     public static void selectionSort(long[] aa, double[] bb, long[] cc, double[] dd){
1510             int index = 0;
1511             int lastIndex = -1;
1512             int n = aa.length;
1513             int m = bb.length;
1514             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1515             int nn = cc.length;
1516             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1517             int mm = dd.length;
1518             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1519 
1520             long holdx = 0L;
1521             double holdy = 0.0D;
1522 
1523 
1524             for(int i=0; i<n; i++){
1525                 cc[i]=aa[i];
1526                 dd[i]=bb[i];
1527             }
1528 
1529             while(lastIndex != n-1){
1530                 index = lastIndex+1;
1531                 for(int i=lastIndex+2; i<n; i++){
1532                     if(cc[i]<cc[index]){
1533                         index=i;
1534                     }
1535                 }
1536                 lastIndex++;
1537                 holdx=cc[index];
1538                 cc[index]=cc[lastIndex];
1539                 cc[lastIndex]=holdx;
1540                 holdy=dd[index];
1541                 dd[index]=dd[lastIndex];
1542                 dd[lastIndex]=holdy;
1543             }
1544        }
1545 
1546 
1547        public static void selectionSort(double[] aa, int[] bb, double[] cc, int[] dd){
1548             int index = 0;
1549             int lastIndex = -1;
1550             int n = aa.length;
1551             int m = bb.length;
1552             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1553             int nn = cc.length;
1554             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1555             int mm = dd.length;
1556             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1557 
1558             double holdx = 0.0D;
1559             int holdy = 0;
1560 
1561 
1562             for(int i=0; i<n; i++){
1563                 cc[i]=aa[i];
1564                 dd[i]=bb[i];
1565             }
1566 
1567             while(lastIndex != n-1){
1568                 index = lastIndex+1;
1569                 for(int i=lastIndex+2; i<n; i++){
1570                     if(cc[i]<cc[index]){
1571                         index=i;
1572                     }
1573                 }
1574                 lastIndex++;
1575                 holdx=cc[index];
1576                 cc[index]=cc[lastIndex];
1577                 cc[lastIndex]=holdx;
1578                 holdy=dd[index];
1579                 dd[index]=dd[lastIndex];
1580                 dd[lastIndex]=holdy;
1581             }
1582        }
1583 
1584        public static void selectionSort(int[] aa, double[] bb, int[] cc, double[] dd){
1585             int index = 0;
1586             int lastIndex = -1;
1587             int n = aa.length;
1588             int m = bb.length;
1589             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1590             int nn = cc.length;
1591             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1592             int mm = dd.length;
1593             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1594 
1595             int holdx = 0;
1596             double holdy = 0.0D;
1597 
1598 
1599             for(int i=0; i<n; i++){
1600                 cc[i]=aa[i];
1601                 dd[i]=bb[i];
1602             }
1603 
1604             while(lastIndex != n-1){
1605                 index = lastIndex+1;
1606                 for(int i=lastIndex+2; i<n; i++){
1607                     if(cc[i]<cc[index]){
1608                         index=i;
1609                     }
1610                 }
1611                 lastIndex++;
1612                 holdx=cc[index];
1613                 cc[index]=cc[lastIndex];
1614                 cc[lastIndex]=holdx;
1615                 holdy=dd[index];
1616                 dd[index]=dd[lastIndex];
1617                 dd[lastIndex]=holdy;
1618             }
1619        }
1620 
1621          public static void selectionSort(long[] aa, int[] bb, long[] cc, int[] dd){
1622             int index = 0;
1623             int lastIndex = -1;
1624             int n = aa.length;
1625             int m = bb.length;
1626             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1627             int nn = cc.length;
1628             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1629             int mm = dd.length;
1630             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1631 
1632             long holdx = 0L;
1633             int holdy = 0;
1634 
1635 
1636             for(int i=0; i<n; i++){
1637                 cc[i]=aa[i];
1638                 dd[i]=bb[i];
1639             }
1640 
1641             while(lastIndex != n-1){
1642                 index = lastIndex+1;
1643                 for(int i=lastIndex+2; i<n; i++){
1644                     if(cc[i]<cc[index]){
1645                         index=i;
1646                     }
1647                 }
1648                 lastIndex++;
1649                 holdx=cc[index];
1650                 cc[index]=cc[lastIndex];
1651                 cc[lastIndex]=holdx;
1652                 holdy=dd[index];
1653                 dd[index]=dd[lastIndex];
1654                 dd[lastIndex]=holdy;
1655             }
1656         }
1657 
1658         public static void selectionSort(int[] aa, long[] bb, int[] cc, long[] dd){
1659             int index = 0;
1660             int lastIndex = -1;
1661             int n = aa.length;
1662             int m = bb.length;
1663             if(n!=m)throw new IllegalArgumentException("First argument array, aa, (length = " + n + ") and the second argument array, bb, (length = " + m + ") should be the same length");
1664             int nn = cc.length;
1665             if(nn<n)throw new IllegalArgumentException("The third argument array, cc, (length = " + nn + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1666             int mm = dd.length;
1667             if(mm<m)throw new IllegalArgumentException("The fourth argument array, dd, (length = " + mm + ") should be at least as long as the second argument array, bb, (length = " + m + ")");
1668 
1669             int holdx = 0;
1670             long holdy = 0L;
1671 
1672 
1673             for(int i=0; i<n; i++){
1674                 cc[i]=aa[i];
1675                 dd[i]=bb[i];
1676             }
1677 
1678             while(lastIndex != n-1){
1679                 index = lastIndex+1;
1680                 for(int i=lastIndex+2; i<n; i++){
1681                     if(cc[i]<cc[index]){
1682                         index=i;
1683                     }
1684                 }
1685                 lastIndex++;
1686                 holdx=cc[index];
1687                 cc[index]=cc[lastIndex];
1688                 cc[lastIndex]=holdx;
1689                 holdy=dd[index];
1690                 dd[index]=dd[lastIndex];
1691                 dd[lastIndex]=holdy;
1692             }
1693        }
1694 
1695 
1696         // sort elements in an array of doubles (first argument) into ascending order
1697         // using selection sort method
1698         // returns the sorted array as second argument
1699         //  and an array of the indices of the sorted array as the third argument
1700         public static void selectSort(double[] aa, double[] bb, int[] indices){
1701             int index = 0;
1702             int lastIndex = -1;
1703             int n = aa.length;
1704             int m = bb.length;
1705             if(m<n)throw new IllegalArgumentException("The second argument array, bb, (length = " + m + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1706             int k = indices.length;
1707             if(m<n)throw new IllegalArgumentException("The third argument array, indices, (length = " + k + ") should be at least as long as the first argument array, aa, (length = " + n + ")");
1708 
1709             double holdb = 0.0D;
1710             int holdi = 0;
1711             for(int i=0; i<n; i++){
1712                 bb[i]=aa[i];
1713                 indices[i]=i;
1714             }
1715 
1716             while(lastIndex != n-1){
1717                 index = lastIndex+1;
1718                 for(int i=lastIndex+2; i<n; i++){
1719                     if(bb[i]<bb[index]){
1720                         index=i;
1721                     }
1722                 }
1723                 lastIndex++;
1724                 holdb=bb[index];
1725                 bb[index]=bb[lastIndex];
1726                 bb[lastIndex]=holdb;
1727                 holdi=indices[index];
1728                 indices[index]=indices[lastIndex];
1729                 indices[lastIndex]=holdi;
1730             }
1731         }
1732 
1733         /*      returns -1 if x < 0 else returns 1   */
1734         //  double version
1735         public static double sign(double x){
1736             if (x<0.0){
1737                 return -1.0;
1738             }
1739             else{
1740                 return 1.0;
1741             }
1742         }
1743 
1744         /*      returns -1 if x < 0 else returns 1   */
1745         //  float version
1746         public static float sign(float x){
1747             if (x<0.0F){
1748                 return -1.0F;
1749             }
1750             else{
1751                 return 1.0F;
1752             }
1753         }
1754 
1755         /*      returns -1 if x < 0 else returns 1   */
1756         //  int version
1757         public static int sign(int x){
1758             if (x<0){
1759                 return -1;
1760             }
1761             else{
1762                 return 1;
1763             }
1764         }
1765 
1766         /*      returns -1 if x < 0 else returns 1   */
1767         // long version
1768         public static long sign(long x){
1769             if (x<0){
1770                 return -1;
1771             }
1772             else{
1773                 return 1;
1774             }
1775         }
1776 
1777         // UNIT CONVERSIONS
1778 
1779         // Converts radians to degrees
1780         public static double radToDeg(double rad){
1781             return  rad*180.0D/Math.PI;
1782         }
1783 
1784         // Converts degrees to radians
1785         public static double degToRad(double deg){
1786             return  deg*Math.PI/180.0D;
1787         }
1788 
1789         // Converts electron volts(eV) to corresponding wavelength in nm
1790         public static double evToNm(double ev){
1791             return  1e+9*C_LIGHT/(-ev*Q_ELECTRON/H_PLANCK);
1792         }
1793 
1794         // Converts wavelength in nm to matching energy in eV
1795         public static double nmToEv(double nm)
1796         {
1797             return  C_LIGHT/(-nm*1e-9)*H_PLANCK/Q_ELECTRON;
1798         }
1799 
1800         // Converts moles per litre to percentage weight by volume
1801         public static double molarToPercentWeightByVol(double molar, double molWeight){
1802             return  molar*molWeight/10.0D;
1803         }
1804 
1805         // Converts percentage weight by volume to moles per litre
1806         public static double percentWeightByVolToMolar(double perCent, double molWeight){
1807             return  perCent*10.0D/molWeight;
1808         }
1809 
1810         // Converts Celsius to Kelvin
1811         public static double celsiusToKelvin(double cels){
1812             return  cels-T_ABS;
1813         }
1814 
1815         // Converts Kelvin to Celsius
1816         public static double kelvinToCelsius(double kelv){
1817             return  kelv+T_ABS;
1818         }
1819 
1820         // Converts Celsius to Fahrenheit
1821         public static double celsiusToFahren(double cels){
1822             return  cels*(9.0/5.0)+32.0;
1823         }
1824 
1825         // Converts Fahrenheit to Celsius
1826         public static double fahrenToCelsius(double fahr){
1827             return  (fahr-32.0)*5.0/9.0;
1828         }
1829 
1830         // Converts calories to Joules
1831         public static double calorieToJoule(double cal){
1832             return  cal*4.1868;
1833         }
1834 
1835         // Converts Joules to calories
1836         public static double jouleToCalorie(double joule){
1837             return  joule*0.23884;
1838         }
1839 
1840         // Converts grams to ounces
1841         public static double gramToOunce(double gm){
1842             return  gm/28.3459;
1843         }
1844 
1845         // Converts ounces to grams
1846         public static double ounceToGram(double oz){
1847             return  oz*28.3459;
1848         }
1849 
1850         // Converts kilograms to pounds
1851         public static double kgToPound(double kg){
1852             return  kg/0.4536;
1853         }
1854 
1855         // Converts pounds to kilograms
1856         public static double poundToKg(double pds){
1857             return  pds*0.4536;
1858         }
1859 
1860         // Converts kilograms to tons
1861         public static double kgToTon(double kg){
1862             return  kg/1016.05;
1863         }
1864 
1865         // Converts tons to kilograms
1866         public static double tonToKg(double tons){
1867             return  tons*1016.05;
1868         }
1869 
1870         // Converts millimetres to inches
1871         public static double millimetreToInch(double mm){
1872             return  mm/25.4;
1873         }
1874 
1875         // Converts inches to millimetres
1876         public static double inchToMillimetre(double in){
1877             return  in*25.4;
1878         }
1879 
1880         // Converts feet to metres
1881         public static double footToMetre(double ft){
1882             return  ft*0.3048;
1883         }
1884 
1885         // Converts metres to feet
1886         public static double metreToFoot(double metre){
1887             return  metre/0.3048;
1888         }
1889 
1890         // Converts yards to metres
1891         public static double yardToMetre(double yd){
1892             return  yd*0.9144;
1893         }
1894 
1895         // Converts metres to yards
1896         public static double metreToYard(double metre){
1897             return  metre/0.9144;
1898         }
1899 
1900         // Converts miles to kilometres
1901         public static double mileToKm(double mile){
1902             return  mile*1.6093;
1903         }
1904 
1905         // Converts kilometres to miles
1906         public static double kmToMile(double km){
1907             return  km/1.6093;
1908         }
1909 
1910         // Converts UK gallons to litres
1911         public static double gallonToLitre(double gall){
1912             return  gall*4.546;
1913         }
1914 
1915         // Converts litres to UK gallons
1916         public static double litreToGallon(double litre){
1917             return  litre/4.546;
1918         }
1919 
1920         // Converts UK quarts to litres
1921         public static double quartToLitre(double quart){
1922             return  quart*1.137;
1923         }
1924 
1925         // Converts litres to UK quarts
1926         public static double litreToQuart(double litre){
1927             return  litre/1.137;
1928         }
1929 
1930         // Converts UK pints to litres
1931         public static double pintToLitre(double pint){
1932             return  pint*0.568;
1933         }
1934 
1935         // Converts litres to UK pints
1936         public static double litreToPint(double litre){
1937             return  litre/0.568;
1938         }
1939 
1940         // Converts UK gallons per mile to litres per kilometre
1941         public static double gallonPerMileToLitrePerKm(double gallPmile){
1942             return  gallPmile*2.825;
1943         }
1944 
1945         // Converts litres per kilometre to UK gallons per mile
1946         public static double litrePerKmToGallonPerMile(double litrePkm){
1947             return  litrePkm/2.825;
1948         }
1949 
1950         // Converts miles per UK gallons to kilometres per litre
1951         public static double milePerGallonToKmPerLitre(double milePgall){
1952             return  milePgall*0.354;
1953         }
1954 
1955         // Converts kilometres per litre to miles per UK gallons
1956         public static double kmPerLitreToMilePerGallon(double kmPlitre){
1957             return  kmPlitre/0.354;
1958         }
1959 
1960         // Converts UK fluid ounce to American fluid ounce
1961         public static double fluidOunceUKtoUS(double flOzUK){
1962             return  flOzUK*0.961;
1963         }
1964 
1965         // Converts American fluid ounce to UK fluid ounce
1966         public static double fluidOunceUStoUK(double flOzUS){
1967             return  flOzUS*1.041;
1968         }
1969 
1970         // Converts UK pint to American liquid pint
1971         public static double pintUKtoUS(double pintUK){
1972             return  pintUK*1.201;
1973         }
1974 
1975         // Converts American liquid pint to UK pint
1976         public static double pintUStoUK(double pintUS){
1977             return  pintUS*0.833;
1978         }
1979 
1980         // Converts UK quart to American liquid quart
1981         public static double quartUKtoUS(double quartUK){
1982             return  quartUK*1.201;
1983         }
1984 
1985         // Converts American liquid quart to UK quart
1986         public static double quartUStoUK(double quartUS){
1987             return  quartUS*0.833;
1988         }
1989 
1990         // Converts UK gallon to American gallon
1991         public static double gallonUKtoUS(double gallonUK){
1992             return  gallonUK*1.201;
1993         }
1994 
1995         // Converts American gallon to UK gallon
1996         public static double gallonUStoUK(double gallonUS){
1997             return  gallonUS*0.833;
1998         }
1999 
2000         // Converts UK pint to American cup
2001         public static double pintUKtoCupUS(double pintUK){
2002             return  pintUK/0.417;
2003         }
2004 
2005         // Converts American cup to UK pint
2006         public static double cupUStoPintUK(double cupUS){
2007             return  cupUS*0.417;
2008         }
2009 
2010         // Calculates body mass index (BMI) from height (m) and weight (kg)
2011         public static double calcBMImetric(double height, double weight){
2012             return  weight/(height*height);
2013         }
2014 
2015         // Calculates body mass index (BMI) from height (ft) and weight (lbs)
2016         public static double calcBMIimperial(double height, double weight){
2017                 height = Fmath.footToMetre(height);
2018                 weight = Fmath.poundToKg(weight);
2019             return  weight/(height*height);
2020         }
2021 
2022         // Calculates weight (kg) to give a specified BMI for a given height (m)
2023         public static double calcWeightFromBMImetric(double bmi, double height){
2024             return bmi*height*height;
2025         }
2026 
2027         // Calculates weight (lbs) to give a specified BMI for a given height (ft)
2028         public static double calcWeightFromBMIimperial(double bmi, double height){
2029             height = Fmath.footToMetre(height);
2030             double weight = bmi*height*height;
2031             weight = Fmath.kgToPound(weight);
2032             return  weight;
2033         }
2034 
2035 
2036         // ADDITIONAL TRIGONOMETRIC FUNCTIONS
2037 
2038         // Returns the length of the hypotenuse of a and b
2039         // i.e. sqrt(a*a+b*b) [without unecessary overflow or underflow]
2040         // double version
2041         public static double hypot(double aa, double bb){
2042             double amod=Math.abs(aa);
2043             double bmod=Math.abs(bb);
2044             double cc = 0.0D, ratio = 0.0D;
2045             if(amod==0.0){
2046                 cc=bmod;
2047             }
2048             else{
2049                 if(bmod==0.0){
2050                     cc=amod;
2051                 }
2052                 else{
2053                     if(amod>=bmod){
2054                         ratio=bmod/amod;
2055                         cc=amod*Math.sqrt(1.0 + ratio*ratio);
2056                     }
2057                     else{
2058                         ratio=amod/bmod;
2059                         cc=bmod*Math.sqrt(1.0 + ratio*ratio);
2060                     }
2061                 }
2062             }
2063             return cc;
2064         }
2065 
2066         // Returns the length of the hypotenuse of a and b
2067         // i.e. sqrt(a*a+b*b) [without unecessary overflow or underflow]
2068         // float version
2069         public static float hypot(float aa, float bb){
2070             return (float) hypot((double) aa, (double) bb);
2071         }
2072 
2073         // Angle (in radians) subtended at coordinate C
2074         // given x, y coordinates of all apices, A, B and C, of a triangle
2075         public static double angle(double xAtA, double yAtA, double xAtB, double yAtB, double xAtC, double yAtC){
2076 
2077             double ccos = Fmath.cos(xAtA, yAtA, xAtB, yAtB, xAtC, yAtC);
2078             return Math.acos(ccos);
2079         }
2080 
2081         // Angle (in radians) between sides sideA and sideB given all side lengths of a triangle
2082         public static double angle(double sideAC, double sideBC, double sideAB){
2083 
2084             double ccos = Fmath.cos(sideAC, sideBC, sideAB);
2085             return Math.acos(ccos);
2086         }
2087 
2088         // Sine of angle subtended at coordinate C
2089         // given x, y coordinates of all apices, A, B and C, of a triangle
2090         public static double sin(double xAtA, double yAtA, double xAtB, double yAtB, double xAtC, double yAtC){
2091             double angle = Fmath.angle(xAtA, yAtA, xAtB, yAtB, xAtC, yAtC);
2092             return Math.sin(angle);
2093         }
2094 
2095         // Sine of angle between sides sideA and sideB given all side lengths of a triangle
2096         public static double sin(double sideAC, double sideBC, double sideAB){
2097             double angle = Fmath.angle(sideAC, sideBC, sideAB);
2098             return Math.sin(angle);
2099         }
2100 
2101         // Sine given angle in radians
2102         // for completion - returns Math.sin(arg)
2103         public static double sin(double arg){
2104             return Math.sin(arg);
2105         }
2106 
2107         // Inverse sine
2108         // Fmath.asin Checks limits - Java Math.asin returns NaN if without limits
2109         public static double asin(double a){
2110             if(a<-1.0D && a>1.0D) throw new IllegalArgumentException("Fmath.asin argument (" + a + ") must be >= -1.0 and <= 1.0");
2111             return Math.asin(a);
2112         }
2113 
2114         // Cosine of angle subtended at coordinate C
2115         // given x, y coordinates of all apices, A, B and C, of a triangle
2116         public static double cos(double xAtA, double yAtA, double xAtB, double yAtB, double xAtC, double yAtC){
2117             double sideAC = Fmath.hypot(xAtA - xAtC, yAtA - yAtC);
2118             double sideBC = Fmath.hypot(xAtB - xAtC, yAtB - yAtC);
2119             double sideAB = Fmath.hypot(xAtA - xAtB, yAtA - yAtB);
2120             return Fmath.cos(sideAC, sideBC, sideAB);
2121         }
2122 
2123         // Cosine of angle between sides sideA and sideB given all side lengths of a triangle
2124         public static double cos(double sideAC, double sideBC, double sideAB){
2125             return 0.5D*(sideAC/sideBC + sideBC/sideAC - (sideAB/sideAC)*(sideAB/sideBC));
2126         }
2127 
2128          // Cosine given angle in radians
2129          // for completion - returns Java Math.cos(arg)
2130         public static double cos(double arg){
2131             return Math.cos(arg);
2132         }
2133 
2134         // Inverse cosine
2135         // Fmath.asin Checks limits - Java Math.asin returns NaN if without limits
2136         public static double acos(double a){
2137             if(a<-1.0D || a>1.0D) throw new IllegalArgumentException("Fmath.acos argument (" + a + ") must be >= -1.0 and <= 1.0");
2138             return Math.acos(a);
2139         }
2140 
2141         // Tangent of angle subtended at coordinate C
2142         // given x, y coordinates of all apices, A, B and C, of a triangle
2143         public static double tan(double xAtA, double yAtA, double xAtB, double yAtB, double xAtC, double yAtC){
2144             double angle = Fmath.angle(xAtA, yAtA, xAtB, yAtB, xAtC, yAtC);
2145             return Math.tan(angle);
2146         }
2147 
2148         // Tangent of angle between sides sideA and sideB given all side lengths of a triangle
2149         public static double tan(double sideAC, double sideBC, double sideAB){
2150             double angle = Fmath.angle(sideAC, sideBC, sideAB);
2151             return Math.tan(angle);
2152         }
2153 
2154         // Tangent given angle in radians
2155         // for completion - returns Math.tan(arg)
2156         public static double tan(double arg){
2157             return Math.tan(arg);
2158         }
2159 
2160         // Inverse tangent
2161         // for completion - returns Math.atan(arg)
2162         public static double atan(double a){
2163             return Math.atan(a);
2164         }
2165 
2166         // Inverse tangent - ratio numerator and denominator provided
2167         // for completion - returns Math.atan2(arg)
2168         public static double atan2(double a, double b){
2169             return Math.atan2(a, b);
2170         }
2171 
2172         // Cotangent
2173         public static double cot(double a){
2174             return 1.0D/Math.tan(a);
2175         }
2176 
2177         // Inverse cotangent
2178         public static double acot(double a){
2179             return Math.atan(1.0D/a);
2180         }
2181 
2182         // Inverse cotangent - ratio numerator and denominator provided
2183         public static double acot2(double a, double b){
2184             return Math.atan2(b, a);
2185         }
2186 
2187         // Secant
2188         public static double sec(double a){
2189             return 1.0/Math.cos(a);
2190         }
2191 
2192         // Inverse secant
2193         public static double asec(double a){
2194             if(a<1.0D && a>-1.0D) throw new IllegalArgumentException("asec argument (" + a + ") must be >= 1 or <= -1");
2195             return Math.acos(1.0/a);
2196         }
2197 
2198         // Cosecant
2199         public static double csc(double a){
2200             return 1.0D/Math.sin(a);
2201         }
2202 
2203         // Inverse cosecant
2204         public static double acsc(double a){
2205             if(a<1.0D && a>-1.0D) throw new IllegalArgumentException("acsc argument (" + a + ") must be >= 1 or <= -1");
2206             return Math.asin(1.0/a);
2207         }
2208 
2209         // Exsecant
2210         public static double exsec(double a){
2211             return (1.0/Math.cos(a)-1.0D);
2212         }
2213 
2214         // Inverse exsecant
2215         public static double aexsec(double a){
2216             if(a<0.0D && a>-2.0D) throw new IllegalArgumentException("aexsec argument (" + a + ") must be >= 0.0 and <= -2");
2217             return Math.asin(1.0D/(1.0D + a));
2218         }
2219 
2220         // Versine
2221         public static double vers(double a){
2222             return (1.0D - Math.cos(a));
2223         }
2224 
2225         // Inverse  versine
2226         public static double avers(double a){
2227             if(a<0.0D && a>2.0D) throw new IllegalArgumentException("avers argument (" + a + ") must be <= 2 and >= 0");
2228             return Math.acos(1.0D - a);
2229         }
2230 
2231         // Coversine
2232         public static double covers(double a){
2233             return (1.0D - Math.sin(a));
2234         }
2235 
2236         // Inverse coversine
2237         public static double acovers(double a){
2238             if(a<0.0D && a>2.0D) throw new IllegalArgumentException("acovers argument (" + a + ") must be <= 2 and >= 0");
2239             return Math.asin(1.0D - a);
2240         }
2241 
2242         // Haversine
2243         public static double hav(double a){
2244             return 0.5D*Fmath.vers(a);
2245         }
2246 
2247         // Inverse haversine
2248         public static double ahav(double a){
2249             if(a<0.0D && a>1.0D) throw new IllegalArgumentException("ahav argument (" + a + ") must be >= 0 and <= 1");
2250             return 0.5D*Fmath.vers(a);
2251         }
2252 
2253         // Sinc
2254         public static double sinc(double a){
2255             if(Math.abs(a)<1e-40){
2256                 return 1.0D;
2257             }
2258             else{
2259                 return Math.sin(a)/a;
2260             }
2261         }
2262 
2263         //Hyperbolic sine of a double number
2264         public static double sinh(double a){
2265             return 0.5D*(Math.exp(a)-Math.exp(-a));
2266         }
2267 
2268         // Inverse hyperbolic sine of a double number
2269         public static double asinh(double a){
2270             double sgn = 1.0D;
2271             if(a<0.0D){
2272                 sgn = -1.0D;
2273                 a = -a;
2274             }
2275             return sgn*Math.log(a+Math.sqrt(a*a+1.0D));
2276         }
2277 
2278         //Hyperbolic cosine of a double number
2279         public static double cosh(double a){
2280             return 0.5D*(Math.exp(a)+Math.exp(-a));
2281         }
2282 
2283         // Inverse hyperbolic cosine of a double number
2284         public static double acosh(double a){
2285             if(a<1.0D) throw new IllegalArgumentException("acosh real number argument (" + a + ") must be >= 1");
2286             return Math.log(a+Math.sqrt(a*a-1.0D));
2287         }
2288 
2289         //Hyperbolic tangent of a double number
2290         public static double tanh(double a){
2291             return sinh(a)/cosh(a);
2292         }
2293 
2294         // Inverse hyperbolic tangent of a double number
2295         public static double atanh(double a){
2296             double sgn = 1.0D;
2297             if(a<0.0D){
2298                 sgn = -1.0D;
2299                 a = -a;
2300             }
2301             if(a>1.0D) throw new IllegalArgumentException("atanh real number argument (" + sgn*a + ") must be >= -1 and <= 1");
2302             return 0.5D*sgn*(Math.log(1.0D + a)-Math.log(1.0D - a));
2303         }
2304 
2305         //Hyperbolic cotangent of a double number
2306         public static double coth(double a){
2307             return 1.0D/tanh(a);
2308         }
2309 
2310         // Inverse hyperbolic cotangent of a double number
2311         public static double acoth(double a){
2312             double sgn = 1.0D;
2313             if(a<0.0D){
2314                 sgn = -1.0D;
2315                 a = -a;
2316             }
2317             if(a<1.0D) throw new IllegalArgumentException("acoth real number argument (" + sgn*a + ") must be <= -1 or >= 1");
2318             return 0.5D*sgn*(Math.log(1.0D + a)-Math.log(a - 1.0D));
2319         }
2320 
2321         //Hyperbolic secant of a double number
2322         public static double sech(double a){
2323                 return 1.0D/cosh(a);
2324         }
2325 
2326         // Inverse hyperbolic secant of a double number
2327         public static double asech(double a){
2328             if(a>1.0D || a<0.0D) throw new IllegalArgumentException("asech real number argument (" + a + ") must be >= 0 and <= 1");
2329             return 0.5D*(Math.log(1.0D/a + Math.sqrt(1.0D/(a*a) - 1.0D)));
2330         }
2331 
2332         //Hyperbolic cosecant of a double number
2333         public static double csch(double a){
2334                 return 1.0D/sinh(a);
2335         }
2336 
2337         // Inverse hyperbolic cosecant of a double number
2338         public static double acsch(double a){
2339             double sgn = 1.0D;
2340             if(a<0.0D){
2341                 sgn = -1.0D;
2342                 a = -a;
2343             }
2344             return 0.5D*sgn*(Math.log(1.0/a + Math.sqrt(1.0D/(a*a) + 1.0D)));
2345         }
2346 
2347     // MANTISSA ROUNDING (TRUNCATING)
2348     // Rounds the mantissa of a double to prec places
2349     public static double truncate(double x, int prec){
2350 
2351         if(prec<0)throw new IllegalArgumentException("precision less than zero places");
2352 
2353         if(x==0.0D)return x;
2354         if(Fmath.isNaN(x))return x;
2355         if(Fmath.isPlusInfinity(x))return x;
2356         if(Fmath.isMinusInfinity(x))return x;
2357 
2358         char sign = ' ';
2359         if(x<0.0D){
2360             sign = '-';
2361             x = -x;
2362         }
2363 
2364         Double xx = new Double(x);
2365         String xString = xx.toString();
2366         String newXstring = stringRound(xString.trim(), prec, sign);
2367 
2368         return Double.parseDouble(newXstring);
2369     }
2370 
2371     // Rounds the mantissa of a float to prec places
2372     public static float truncate(float x, int prec){
2373 
2374         if(prec<0)throw new IllegalArgumentException("precision less than zero places");
2375 
2376         if(x==0.0D)return x;
2377         if(Fmath.isNaN(x))return x;
2378         if(Fmath.isPlusInfinity(x))return x;
2379         if(Fmath.isMinusInfinity(x))return x;
2380 
2381         char sign = ' ';
2382         if(x<0.0D){
2383             sign = '-';
2384             x = -x;
2385         }
2386 
2387         Float xx = new Float(x);
2388         String xString = xx.toString();
2389         String newXstring = stringRound(xString.trim(), prec, sign);
2390         return Float.parseFloat(newXstring);
2391     }
2392 
2393     //Method for truncate
2394     private static String stringRound(String ss, int prec, char sign){
2395 
2396         String returnString = null;     // truncated number as a String
2397         int posEnd = ss.length()-1;     // end character index
2398         int posE = ss.indexOf('E');     // Exponent E index
2399         int posDot = ss.indexOf('.');   // decimal point index
2400 
2401         String decPlaces = null;        // number of decimal places
2402         String exponent = null;         // exponent as a String
2403         String prePoint = ss.substring(0, posDot);  // digits before decimal place as a String
2404         int ppLen = prePoint.length();  // number of digits before the point
2405 
2406         if(posE==-1){
2407             decPlaces = ss.substring(posDot+1);
2408         }
2409         else{
2410             decPlaces = ss.substring(posDot+1, posE);
2411             exponent = ss.substring(posE+1);
2412         }
2413         int dpLen = decPlaces.length();
2414 
2415         // Return for truncation to zero decimal places
2416         if(prec==0){
2417             returnString = prePoint + ".0";
2418             if(exponent!=null)returnString = returnString + "E" + exponent;
2419             if(sign=='-')returnString = "-" + returnString;
2420             return returnString;
2421         }
2422 
2423         // Return if number of decimal places required by truncation is greater than the actual number of decimal placess
2424         if(dpLen<=prec){
2425             returnString = ss;
2426             if(sign=='-')returnString = "-" + ss;
2427             return returnString;
2428         }
2429 
2430         // Check for 0. and then all nines before and one place after the truncation point
2431         boolean test9 = true;
2432         boolean test9end=false;
2433         if(posE==-1){
2434             if(ss.charAt(0)!='0'){
2435                 test9=false;
2436             }
2437             else{
2438                 if(ss.charAt(1)!='.'){
2439                     test9=false;
2440                 }
2441                 else{
2442                     for(int i=2; i<2+prec; i++){
2443                         if(ss.charAt(i)!='9'){
2444                             test9 = false;
2445                         }
2446                         if(!test9)break;
2447                     }
2448                     if(test9 && ss.charAt(prec+2)>'4')test9end=true;
2449                 }
2450             }
2451             if(test9){
2452                 if(test9end){
2453                     returnString = "1.";
2454                     for(int i = 1; i<=prec; i++)returnString += '0';
2455                     if(sign=='-')returnString = "-" + returnString;
2456                     return returnString;
2457                 }
2458                 else{
2459                     returnString = "0.";
2460                     for(int i = 1; i<=prec; i++)returnString += '9';
2461                     if(sign=='-')returnString = "-" + returnString;
2462                     return returnString;
2463                 }
2464             }
2465         }
2466 
2467         // all other truncations
2468         int[] iss = new int[dpLen];
2469         int carry = 0;
2470         for(int i=dpLen-1; i>=prec; i--){
2471              iss[i] = (int)decPlaces.charAt(i) + carry;
2472              if(iss[i]<53){
2473                 carry = 0;
2474              }
2475              else{
2476                 carry = 1;
2477              }
2478              iss[i] = 48;
2479         }
2480         boolean test = true;
2481         int ii = prec - 1;
2482         while(test){
2483             iss[ii] = (int)decPlaces.charAt(ii) + carry;
2484             if(iss[ii]<58){
2485                 test=false;
2486                 for(int i = 0; i<ii; i++){
2487                     iss[i] = (int)decPlaces.charAt(i);
2488                 }
2489                 carry = 0;
2490             }
2491             else{
2492                iss[ii] = 48;
2493                carry = 1;
2494                ii--;
2495                if(ii<0)test=false;
2496             }
2497         }
2498 
2499         test = true;
2500         if(carry==0)test = false;
2501         ii = posDot - 1;
2502         while(test){
2503             iss[ii] = (int)prePoint.charAt(ii) + carry;
2504             if(iss[ii]<58){
2505                 test=false;
2506                 for(int i = 0; i<ii; i++){
2507                     iss[i] = (int)prePoint.charAt(i);
2508                 }
2509                 carry = 0;
2510             }
2511             else{
2512                iss[ii] = 48;
2513                carry = 1;
2514                ii--;
2515                if(ii<0)test=false;
2516             }
2517         }
2518 
2519         if(carry==1){
2520             prePoint = "1";
2521             for(int i=0; i<ppLen; i++)prePoint = prePoint + "0";
2522             returnString = prePoint + ".0";
2523 
2524         }
2525         else{
2526             returnString = prePoint + ".";
2527             StringBuffer strbuff = new StringBuffer();
2528             for(int k=0; k<prec; k++){
2529                 strbuff.append((char)iss[k]);
2530             }
2531             returnString = returnString + strbuff.toString();
2532         }
2533 
2534         if(exponent!=null)returnString = returnString + "E" + exponent;
2535         if(sign=='-')returnString = "-" + returnString;
2536 
2537         return returnString;
2538     }
2539 
2540 
2541 
2542         // Returns true if x is infinite, i.e. is equal to either plus or minus infinity
2543         // x is double
2544         public static boolean isInfinity(double x){
2545             boolean test=false;
2546             if(x==Double.POSITIVE_INFINITY || x==Double.NEGATIVE_INFINITY)test=true;
2547             return test;
2548         }
2549 
2550         // Returns true if x is infinite, i.e. is equal to either plus or minus infinity
2551         // x is float
2552         public static boolean isInfinity(float x){
2553             boolean test=false;
2554             if(x==Float.POSITIVE_INFINITY || x==Float.NEGATIVE_INFINITY)test=true;
2555             return test;
2556         }
2557 
2558         // Returns true if x is plus infinity
2559         // x is double
2560         public static boolean isPlusInfinity(double x){
2561             boolean test=false;
2562             if(x==Double.POSITIVE_INFINITY)test=true;
2563             return test;
2564         }
2565 
2566         // Returns true if x is plus infinity
2567         // x is float
2568         public static boolean isPlusInfinity(float x){
2569             boolean test=false;
2570             if(x==Float.POSITIVE_INFINITY)test=true;
2571             return test;
2572         }
2573 
2574         // Returns true if x is minus infinity
2575         // x is double
2576         public static boolean isMinusInfinity(double x){
2577             boolean test=false;
2578             if(x==Double.NEGATIVE_INFINITY)test=true;
2579             return test;
2580         }
2581 
2582         // Returns true if x is minus infinity
2583         // x is float
2584         public static boolean isMinusInfinity(float x){
2585             boolean test=false;
2586             if(x==Float.NEGATIVE_INFINITY)test=true;
2587             return test;
2588         }
2589 
2590 
2591         // Returns true if x is 'Not a Number' (NaN)
2592         // x is double
2593         public static boolean isNaN(double x){
2594             boolean test=false;
2595             if(x!=x)test=true;
2596             return test;
2597         }
2598 
2599         // Returns true if x is 'Not a Number' (NaN)
2600         // x is float
2601         public static boolean isNaN(float x){
2602             boolean test=false;
2603             if(x!=x)test=true;
2604             return test;
2605         }
2606 
2607         // Returns true if x equals y
2608         // x and y are double
2609         // x may be float within range, PLUS_INFINITY, NEGATIVE_INFINITY, or NaN
2610         // NB!! This method treats two NaNs as equal
2611         public static boolean isEqual(double x, double y){
2612             boolean test=false;
2613             if(Fmath.isNaN(x)){
2614                 if(Fmath.isNaN(y))test=true;
2615             }
2616             else{
2617                 if(Fmath.isPlusInfinity(x)){
2618                     if(Fmath.isPlusInfinity(y))test=true;
2619                 }
2620                 else{
2621                     if(Fmath.isMinusInfinity(x)){
2622                         if(Fmath.isMinusInfinity(y))test=true;
2623                     }
2624                     else{
2625                         if(x==y)test=true;
2626                     }
2627                 }
2628             }
2629             return test;
2630         }
2631 
2632         // Returns true if x equals y
2633         // x and y are float
2634         // x may be float within range, PLUS_INFINITY, NEGATIVE_INFINITY, or NaN
2635         // NB!! This method treats two NaNs as equal
2636         public static boolean isEqual(float x, float y){
2637             boolean test=false;
2638             if(Fmath.isNaN(x)){
2639                 if(Fmath.isNaN(y))test=true;
2640             }
2641             else{
2642                 if(Fmath.isPlusInfinity(x)){
2643                     if(Fmath.isPlusInfinity(y))test=true;
2644                 }
2645                 else{
2646                     if(Fmath.isMinusInfinity(x)){
2647                         if(Fmath.isMinusInfinity(y))test=true;
2648                     }
2649                     else{
2650                         if(x==y)test=true;
2651                     }
2652                 }
2653             }
2654             return test;
2655         }
2656 
2657         // Returns true if x equals y
2658         // x and y are int
2659         public static boolean isEqual(int x, int y){
2660             boolean test=false;
2661             if(x==y)test=true;
2662             return test;
2663         }
2664 
2665         // Returns true if x equals y
2666         // x and y are char
2667         public static boolean isEqual(char x, char y){
2668             boolean test=false;
2669             if(x==y)test=true;
2670             return test;
2671         }
2672 
2673         // Returns true if x equals y
2674         // x and y are Strings
2675         public static boolean isEqual(String x, String y){
2676             boolean test=false;
2677             if(x.equals(y))test=true;
2678             return test;
2679         }
2680 
2681         // Returns true if x is an even number, false if x is an odd number
2682         // x is int
2683         public static boolean isEven(int x){
2684             boolean test=false;
2685             if(x%2 == 0.0D)test=true;
2686             return test;
2687         }
2688 
2689         // Returns 0 if x == y
2690         // Returns -1 if x < y
2691         // Returns 1 if x > y
2692         // x and y are double
2693         public static int compare(double x, double y){
2694             Double X = new Double(x);
2695             Double Y = new Double(y);
2696             return X.compareTo(Y);
2697         }
2698 
2699         // Returns 0 if x == y
2700         // Returns -1 if x < y
2701         // Returns 1 if x > y
2702         // x and y are int
2703         public static int compare(int x, int y){
2704             Integer X = new Integer(x);
2705             Integer Y = new Integer(y);
2706             return X.compareTo(Y);
2707         }
2708 
2709         // Returns 0 if x == y
2710         // Returns -1 if x < y
2711         // Returns 1 if x > y
2712         // x and y are long
2713         public static int compare(long x, long y){
2714             Long X = new Long(x);
2715             Long Y = new Long(y);
2716             return X.compareTo(Y);
2717         }
2718 
2719         // Returns 0 if x == y
2720         // Returns -1 if x < y
2721         // Returns 1 if x > y
2722         // x and y are float
2723         public static int compare(float x, float y){
2724             Float X = new Float(x);
2725             Float Y = new Float(y);
2726             return X.compareTo(Y);
2727         }
2728 
2729         // Returns 0 if x == y
2730         // Returns -1 if x < y
2731         // Returns 1 if x > y
2732         // x and y are short
2733         public static int compare(byte x, byte y){
2734             Byte X = new Byte(x);
2735             Byte Y = new Byte(y);
2736             return X.compareTo(Y);
2737         }
2738 
2739         // Returns 0 if x == y
2740         // Returns -1 if x < y
2741         // Returns 1 if x > y
2742         // x and y are short
2743         public static int compare(short x, short y){
2744             Short X = new Short(x);
2745             Short Y = new Short(y);
2746             return X.compareTo(Y);
2747         }
2748 
2749         // Returns true if x is an even number, false if x is an odd number
2750         // x is float but must hold an integer value
2751         public static boolean isEven(float x){
2752             double y=Math.floor(x);
2753             if(((double)x - y)!= 0.0D)throw new IllegalArgumentException("the argument is not an integer");
2754             boolean test=false;
2755             y=Math.floor(x/2.0F);
2756             if(((double)(x/2.0F)-y) == 0.0D)test=true;
2757             return test;
2758         }
2759 
2760         // Returns true if x is an even number, false if x is an odd number
2761         // x is double but must hold an integer value
2762         public static boolean isEven(double x){
2763             double y=Math.floor(x);
2764             if((x - y)!= 0.0D)throw new IllegalArgumentException("the argument is not an integer");
2765             boolean test=false;
2766             y=Math.floor(x/2.0F);
2767             if((x/2.0D-y) == 0.0D)test=true;
2768             return test;
2769         }
2770 
2771         // Returns true if x is an odd number, false if x is an even number
2772         // x is int
2773         public static boolean isOdd(int x){
2774             boolean test=true;
2775             if(x%2 == 0.0D)test=false;
2776             return test;
2777         }
2778 
2779         // Returns true if x is an odd number, false if x is an even number
2780         // x is float but must hold an integer value
2781         public static boolean isOdd(float x){
2782             double y=Math.floor(x);
2783             if(((double)x - y)!= 0.0D)throw new IllegalArgumentException("the argument is not an integer");
2784             boolean test=true;
2785             y=Math.floor(x/2.0F);
2786             if(((double)(x/2.0F)-y) == 0.0D)test=false;
2787             return test;
2788         }
2789 
2790         // Returns true if x is an odd number, false if x is an even number
2791         // x is double but must hold an integer value
2792         public static boolean isOdd(double x){
2793             double y=Math.floor(x);
2794             if((x - y)!= 0.0D)throw new IllegalArgumentException("the argument is not an integer");
2795             boolean test=true;
2796             y=Math.floor(x/2.0F);
2797             if((x/2.0D-y) == 0.0D)test=false;
2798             return test;
2799         }
2800 
2801         // Returns true if year (argument) is a leap year
2802         public static boolean leapYear(int year){
2803             boolean test = false;
2804 
2805             if(year%4 != 0){
2806                  test = false;
2807             }
2808             else{
2809                 if(year%400 == 0){
2810                     test=true;
2811                 }
2812                 else{
2813                     if(year%100 == 0){
2814                         test=false;
2815                     }
2816                     else{
2817                         test=true;
2818                     }
2819                 }
2820             }
2821             return test;
2822         }
2823 
2824         // Returns milliseconds since 0 hours 0 minutes 0 seconds on 1 Jan 1970
2825         public static long dateToJavaMilliS(int year, int month, int day, int hour, int min, int sec){
2826 
2827             long[] monthDays = {0L, 31L, 28L, 31L, 30L, 31L, 30L, 31L, 31L, 30L, 31L, 30L, 31L};
2828             long ms = 0L;
2829 
2830             long yearDiff = 0L;
2831             int yearTest = year-1;
2832             while(yearTest>=1970){
2833                 yearDiff += 365;
2834                 if(Fmath.leapYear(yearTest))yearDiff++;
2835                 yearTest--;
2836             }
2837             yearDiff *= 24L*60L*60L*1000L;
2838 
2839             long monthDiff = 0L;
2840             int monthTest = month -1;
2841             while(monthTest>0){
2842                 monthDiff += monthDays[monthTest];
2843                 if(Fmath.leapYear(year))monthDiff++;
2844                 monthTest--;
2845             }
2846 
2847             monthDiff *= 24L*60L*60L*1000L;
2848 
2849             ms = yearDiff + monthDiff + day*24L*60L*60L*1000L + hour*60L*60L*1000L + min*60L*1000L + sec*1000L;
2850 
2851             return ms;
2852         }
2853 
2854 }