Coverage Report - org.galagosearch.core.eval.stat.Stat
 
Classes in this File Line Coverage Branch Coverage Complexity
Stat
0%
0/1036
0%
0/518
2.993
 
 1  
 /*
 2  
 *   org.galagosearch.eval.stat note:
 3  
 *       This is an abridged version of the Stat class provided by Dr. Michael Flanagan.
 4  
 *       The full version contains many more features.  This class has been trimmed to
 5  
 *       contain primarily the functions necessary for IR evaluation.
 6  
 *          http://www.ee.ucl.ac.uk/~mflanaga/java/
 7  
 *
 8  
 *   Class   Stat
 9  
 *
 10  
 *   USAGE:  Statistical functions
 11  
 *
 12  
 *   WRITTEN BY: Dr Michael Thomas Flanagan
 13  
 *
 14  
 *   DATE:    June 2002 as part of Fmath
 15  
 *   AMENDED: 12 May 2003 Statistics separated out from Fmath as a new class
 16  
 *   UPDATE:  18 June 2005, 5 January 2006, 25 April 2006, 12, 21 November 2006
 17  
 *
 18  
 *   DOCUMENTATION:
 19  
 *   See Michael Thomas Flanagan's Java library on-line web page:
 20  
 *   Stat.html
 21  
 *
 22  
 *   Copyright (c) April 2004, June 2005, January 2006, November 2006
 23  
 *
 24  
 *   PERMISSION TO COPY:
 25  
 *   Permission to use, copy and modify this software and its documentation for
 26  
 *   NON-COMMERCIAL purposes is granted, without fee, provided that an acknowledgement
 27  
 *   to the author, Michael Thomas Flanagan at www.ee.ucl.ac.uk/~mflanaga, appears in all copies.
 28  
 *
 29  
 *   Dr Michael Thomas Flanagan makes no representations about the suitability
 30  
 *   or fitness of the software for any or for a particular purpose.
 31  
 *   Michael Thomas Flanagan shall not be liable for any damages suffered
 32  
 *   as a result of using, modifying or distributing this software or its derivatives.
 33  
 *
 34  
 ***************************************************************************************/
 35  
 
 36  
 package org.galagosearch.core.eval.stat;
 37  
 
 38  
 import java.util.*;
 39  
 
 40  0
 public class Stat{
 41  
 
 42  
 
 43  
         // A small number close to the smallest representable floating point number
 44  
         public static final double FPMIN = 1e-300;
 45  
 
 46  
         // PRIVATE MEMBERS FOR USE IN GAMMA FUNCTION METHODS AND HISTOGRAM CONSTRUCTION METHODS
 47  
 
 48  
         // GAMMA FUNCTIONS
 49  
         //  Lanczos Gamma Function approximation - N (number of coefficients -1)
 50  0
         private static int lgfN = 6;
 51  
         //  Lanczos Gamma Function approximation - Coefficients
 52  0
         private static double[] lgfCoeff = {1.000000000190015, 76.18009172947146, -86.50532032941677, 24.01409824083091, -1.231739572450155, 0.1208650973866179E-2, -0.5395239384953E-5};
 53  
         //  Lanczos Gamma Function approximation - small gamma
 54  0
         private static double lgfGamma = 5.0;
 55  
         //  Maximum number of iterations allowed in Incomplete Gamma Function calculations
 56  0
         private static int igfiter = 1000;
 57  
         //  Tolerance used in terminating series in Incomplete Gamma Function calculations
 58  0
         private static double igfeps = 1e-8;
 59  
 
 60  
         // HISTOGRAM CONSTRUCTION
 61  
         //  Tolerance used in including an upper point in last histogram bin when it is outside due to riunding erors
 62  0
         private static double histTol = 1.0001D;
 63  
 
 64  
         // METHODS
 65  
 
 66  
         // Arithmetic mean of a 1D array of doubles, aa
 67  
         public static double mean(double[] aa){
 68  0
                 int n = aa.length;
 69  0
                 double sum=0.0D;
 70  0
                 for(int i=0; i<n; i++){
 71  0
                         sum+=aa[i];
 72  
                 }
 73  0
                 return sum/((double)n);
 74  
         }
 75  
 
 76  
         // Weighted arithmetic mean of a 1D array of doubles, aa
 77  
         public static double mean(double[] aa, double[] ww){
 78  0
                 int n = aa.length;
 79  0
                 if(n!=ww.length)throw new IllegalArgumentException("length of variable array, " + n + " and length of weight array, " + ww.length + " are different");
 80  0
                 double sumx=0.0D;
 81  0
                 double sumw=0.0D;
 82  0
                 double weight = 0.0D;
 83  0
                 for(int i=0; i<n; i++){
 84  0
                     weight = 1.0D/(ww[i]*ww[i]);
 85  0
                     sumx+=aa[i]*weight;
 86  0
                     sumw+=weight;
 87  
                 }
 88  0
                 return sumx/sumw;
 89  
         }
 90  
 
 91  
         // Weighted arithmetic mean of a 1D array of floats, aa
 92  
         public static double mean(float[] aa, float[] ww){
 93  0
                 int n = aa.length;
 94  0
                 if(n!=ww.length)throw new IllegalArgumentException("length of variable array, " + n + " and length of weight array, " + ww.length + " are different");
 95  0
                 float sumx=0.0F;
 96  0
                 float sumw=0.0F;
 97  0
                 float weight = 0.0F;
 98  0
                 for(int i=0; i<n; i++){
 99  0
                     weight = 1.0F/(ww[i]*ww[i]);
 100  0
                     sumx+=aa[i]*weight;
 101  0
                     sumw+=weight;
 102  
                 }
 103  0
                 return sumx/sumw;
 104  
         }
 105  
 
 106  
         // Geometric mean of a 1D array of doubles, aa
 107  
         public static double geometricMean(double[] aa){
 108  0
                 int n = aa.length;
 109  0
                 double product=1.0D;
 110  0
                 for(int i=0; i<n; i++)product *= Math.pow(aa[i], 1.0D/((double)n));
 111  0
                 return product;
 112  
         }
 113  
 
 114  
         // Geometric mean of a 1D array of floats, aa
 115  
         public static float geometricMean(float[] aa){
 116  0
                 int n = aa.length;
 117  0
                 float product=1.0F;
 118  0
                 for(int i=0; i<n; i++)product *= (float)Math.pow(aa[i], 1.0F/((float)n));
 119  0
                 return product;
 120  
         }
 121  
 
 122  
         // Weighted geometric mean of a 1D array of doubles, aa
 123  
         public static double geometricMean(double[] aa, double[] ww){
 124  0
                 int n = aa.length;
 125  0
                 double sumW = 0.0D;
 126  0
                 double[] weight = new double[n];
 127  0
                 for(int i=0; i<n; i++){
 128  0
                     weight[i]=1.0D/(ww[i]*ww[i]);
 129  0
                     sumW += ww[i];
 130  
                 }
 131  0
                 double product=1.0D;
 132  0
                 for(int i=0; i<n; i++){
 133  0
                     product *= Math.pow(aa[i], weight[i]/sumW);
 134  
                 }
 135  0
                 return product;
 136  
         }
 137  
 
 138  
         // Weighted geometric mean of a 1D array of floats, aa
 139  
         public static float geometricMean(float[] aa, float[] ww){
 140  0
                 int n = aa.length;
 141  0
                 float sumW = 0.0F;
 142  0
                 float[] weight = new float[n];
 143  0
                 for(int i=0; i<n; i++){
 144  0
                     weight[i]=1.0F/(ww[i]*ww[i]);
 145  0
                     sumW += ww[i];
 146  
                 }
 147  0
                 float product=1.0F;
 148  0
                 for(int i=0; i<n; i++){
 149  0
                     product *= (float)Math.pow(aa[i], weight[i]/sumW);
 150  
                 }
 151  0
                 return product;
 152  
         }
 153  
 
 154  
         // Harmonic mean of a 1D array of doubles, aa
 155  
         public static double harmonicMean(double[] aa){
 156  0
                 int n = aa.length;
 157  0
                 double sum = 0.0D;
 158  0
                 for(int i=0; i<n; i++)sum += 1.0D/aa[i];
 159  0
                 return (double)n/sum;
 160  
         }
 161  
 
 162  
         // Harmonic mean of a 1D array of floats, aa
 163  
         public static float harmonicMean(float[] aa){
 164  0
                 int n = aa.length;
 165  0
                 float sum = 0.0F;
 166  0
                 for(int i=0; i<n; i++)sum += 1.0F/aa[i];
 167  0
                 return (float)n/sum;
 168  
         }
 169  
 
 170  
         // Weighted harmonic mean of a 1D array of doubles, aa
 171  
         public static double harmonicMean(double[] aa, double[] ww){
 172  0
                 int n = aa.length;
 173  0
                 double sum = 0.0D;
 174  0
                 double sumW = 0.0D;
 175  0
                 double[] weight = new double[n];
 176  0
                 for(int i=0; i<n; i++){
 177  0
                     sumW += ww[i];
 178  0
                     weight[i]=1.0D/(ww[i]*ww[i]);
 179  
                 }
 180  0
                 for(int i=0; i<n; i++)sum += ww[i]/aa[i];
 181  0
                 return sumW/sum;
 182  
         }
 183  
 
 184  
         // Weighted harmonic mean of a 1D array of floats, aa
 185  
         public static float harmonicMean(float[] aa, float[] ww){
 186  0
                 int n = aa.length;
 187  0
                 float sum = 0.0F;
 188  0
                 float sumW = 0.0F;
 189  0
                 float[] weight = new float[n];
 190  0
                 for(int i=0; i<n; i++){
 191  0
                     sumW += ww[i];
 192  0
                     weight[i]=1.0F/(ww[i]*ww[i]);
 193  
                 }
 194  0
                 for(int i=0; i<n; i++)sum += ww[i]/aa[i];
 195  0
                 return sumW/sum;
 196  
         }
 197  
 
 198  
         // Generalised mean of a 1D array of doubles, aa
 199  
         public static double generalisedMean(double[] aa, double m){
 200  0
                 int n = aa.length;
 201  0
                 double sum=0.0D;
 202  0
                 for(int i=0; i<n; i++){
 203  0
                         sum += Math.pow(aa[i],m);
 204  
                 }
 205  0
                 return Math.pow(sum/((double)n), 1.0D/m);
 206  
         }
 207  
 
 208  
         // Generalised mean of a 1D array of floats, aa
 209  
         public static float generalisedMean(float[] aa, float m){
 210  0
                 int n = aa.length;
 211  0
                 float sum=0.0F;
 212  0
                 for(int i=0; i<n; i++){
 213  0
                         sum += Math.pow(aa[i],m);
 214  
                 }
 215  0
                 return (float)Math.pow(sum/((float)n), 1.0F/m);
 216  
         }
 217  
 
 218  
         // Interquartile mean of a 1D array of doubles, aa
 219  
         public static double interQuartileMean(double[] aa){
 220  0
                 int n = aa.length;
 221  0
                 if(n<4)throw new IllegalArgumentException("At least 4 array elements needed");
 222  0
                 double[] bb = Fmath.selectionSort(aa);
 223  0
                 double sum = 0.0D;
 224  0
                 for(int i=n/4; i<3*n/4; i++)sum += bb[i];
 225  0
                 return 2.0*sum/(double)(n);
 226  
         }
 227  
 
 228  
         // Interquartile mean of a 1D array of floats, aa
 229  
         public static float interQuartileMean(float[] aa){
 230  0
                 int n = aa.length;
 231  0
                 if(n<4)throw new IllegalArgumentException("At least 4 array elements needed");
 232  0
                 float[] bb = Fmath.selectionSort(aa);
 233  0
                 float sum = 0.0F;
 234  0
                 for(int i=n/4; i<3*n/4; i++)sum += bb[i];
 235  0
                 return 2.0F*sum/(float)(n);
 236  
         }
 237  
 
 238  
        // Root mean square (rms) of a 1D array of doubles, aa
 239  
         public static double rms(double[] aa){
 240  0
                 int n = aa.length;
 241  0
                 double sum=0.0D;
 242  0
                 for(int i=0; i<n; i++){
 243  0
                         sum+=aa[i]*aa[i];
 244  
                 }
 245  0
                 return Math.sqrt(sum/((double)n));
 246  
         }
 247  
 
 248  
         // Root mean square (rms) of a 1D array of floats, aa
 249  
         public static float rms(float[] aa){
 250  0
                 int n = aa.length;
 251  0
                 float sum = 0.0F;
 252  0
                 for(int i=0; i<n; i++){
 253  0
                         sum+=aa[i]*aa[i];
 254  
                 }
 255  0
                 sum /= (float)n;
 256  
 
 257  0
                 return (float)Math.sqrt(sum);
 258  
         }
 259  
 
 260  
         // Arithmetic mean of a 1D array of floats, aa
 261  
         public static float mean(float[] aa){
 262  0
                 int n = aa.length;
 263  0
                 float sum=0.0F;
 264  0
                 for(int i=0; i<n; i++){
 265  0
                         sum+=aa[i];
 266  
                 }
 267  0
                 return sum/((float)n);
 268  
         }
 269  
 
 270  
         // Arithmetic mean of a 1D array of int, aa
 271  
         public static double mean(int[] aa){
 272  0
                 int n = aa.length;
 273  0
                 double sum=0.0D;
 274  0
                 for(int i=0; i<n; i++){
 275  0
                         sum+=(double)aa[i];
 276  
                 }
 277  0
                 return sum/((double)n);
 278  
         }
 279  
 
 280  
              // Arithmetic mean of a 1D array of long, aa
 281  
         public static double mean(long[] aa){
 282  0
                 int n = aa.length;
 283  0
                 double sum=0.0D;
 284  0
                 for(int i=0; i<n; i++){
 285  0
                         sum+=(double)aa[i];
 286  
                 }
 287  0
                 return sum/((double)n);
 288  
         }
 289  
 
 290  
         // Median of a 1D array of doubles, aa
 291  
         public static double median(double[] aa){
 292  0
                 int n = aa.length;
 293  0
                 int nOverTwo = n/2;
 294  0
                 double med = 0.0D;
 295  0
                 double[] bb = Fmath.selectionSort(aa);
 296  0
                 if(Fmath.isOdd(n)){
 297  0
                     med = bb[nOverTwo];
 298  
                 }
 299  
                 else{
 300  0
                     med = (bb[nOverTwo-1]+bb[nOverTwo])/2.0D;
 301  
                 }
 302  
 
 303  0
                 return med;
 304  
         }
 305  
 
 306  
         // Median of a 1D array of floats, aa
 307  
         public static float median(float[] aa){
 308  0
                 int n = aa.length;
 309  0
                 int nOverTwo = n/2;
 310  0
                 float med = 0.0F;
 311  0
                 float[] bb = Fmath.selectionSort(aa);
 312  0
                 if(Fmath.isOdd(n)){
 313  0
                     med = bb[nOverTwo];
 314  
                 }
 315  
                 else{
 316  0
                     med = (bb[nOverTwo-1]+bb[nOverTwo])/2.0F;
 317  
                 }
 318  
 
 319  0
                 return med;
 320  
         }
 321  
 
 322  
         // Median of a 1D array of int, aa
 323  
         public static double median(int[] aa){
 324  0
                 int n = aa.length;
 325  0
                 int nOverTwo = n/2;
 326  0
                 double med = 0.0D;
 327  0
                 int[] bb = Fmath.selectionSort(aa);
 328  0
                 if(Fmath.isOdd(n)){
 329  0
                     med = (double)bb[nOverTwo];
 330  
                 }
 331  
                 else{
 332  0
                     med = (double)(bb[nOverTwo-1]+bb[nOverTwo])/2.0D;
 333  
                 }
 334  
 
 335  0
                 return med;
 336  
         }
 337  
 
 338  
         // Median of a 1D array of long, aa
 339  
         public static double median(long[] aa){
 340  0
                 int n = aa.length;
 341  0
                 int nOverTwo = n/2;
 342  0
                 double med = 0.0D;
 343  0
                 long[] bb = Fmath.selectionSort(aa);
 344  0
                 if(Fmath.isOdd(n)){
 345  0
                     med = (double)bb[nOverTwo];
 346  
                 }
 347  
                 else{
 348  0
                     med = (double)(bb[nOverTwo-1]+bb[nOverTwo])/2.0D;
 349  
                 }
 350  
 
 351  0
                 return med;
 352  
         }
 353  
 
 354  
         // Standard deviation of a 1D array of doubles, aa
 355  
         public static double standardDeviation(double[] aa){
 356  0
                 return Math.sqrt(variance(aa));
 357  
         }
 358  
 
 359  
         // Standard deviation of a 1D array of floats, aa
 360  
         public static float standardDeviation(float[] aa){
 361  0
                 return (float)Math.sqrt(variance(aa));
 362  
         }
 363  
 
 364  
         // Standard deviation of a 1D array of int, aa
 365  
         public static double standardDeviation(int[] aa){
 366  0
                 return Math.sqrt(variance(aa));
 367  
         }
 368  
 
 369  
         // Standard deviation of a 1D array of long, aa
 370  
         public static double standardDeviation(long[] aa){
 371  0
                 return Math.sqrt(variance(aa));
 372  
         }
 373  
 
 374  
         // Weighted standard deviation of a 1D array of doubles, aa
 375  
         public static double standardDeviation(double[] aa, double[] ww){
 376  0
                 if(aa.length!=ww.length)throw new IllegalArgumentException("length of variable array, " + aa.length + " and length of weight array, " + ww.length + " are different");
 377  0
                 return Math.sqrt(variance(aa, ww));
 378  
         }
 379  
 
 380  
         // Weighted standard deviation of a 1D array of floats, aa
 381  
         public static float standardDeviation(float[] aa, float[] ww){
 382  0
                 if(aa.length!=ww.length)throw new IllegalArgumentException("length of variable array, " + aa.length + " and length of weight array, " + ww.length + " are different");
 383  0
                 return (float)Math.sqrt(variance(aa, ww));
 384  
         }
 385  
 
 386  
 
 387  
 
 388  
         // volatility   log  (doubles)
 389  
         public static double volatilityLogChange(double[] array){
 390  0
             int n = array.length-1;
 391  0
             double[] change = new double[n];
 392  0
             for(int i=0; i<n; i++)change[i] = Math.log(array[i+1]/array[i]);
 393  0
             return Stat.standardDeviation(change);
 394  
         }
 395  
 
 396  
         // volatility   log  (floats)
 397  
         public static float volatilityLogChange(float[] array){
 398  0
             int n = array.length-1;
 399  0
             float[] change = new float[n];
 400  0
             for(int i=0; i<n; i++)change[i] = (float)Math.log(array[i+1]/array[i]);
 401  0
             return Stat.standardDeviation(change);
 402  
         }
 403  
 
 404  
         // volatility   percentage (double)
 405  
         public static double volatilityPerCentChange(double[] array){
 406  0
             int n = array.length-1;
 407  0
             double[] change = new double[n];
 408  0
             for(int i=0; i<n; i++)change[i] = (array[i+1] - array[i])*100.0D/array[i];
 409  0
             return Stat.standardDeviation(change);
 410  
         }
 411  
 
 412  
         // volatility   percentage (float)
 413  
         public static double volatilityPerCentChange(float[] array){
 414  0
             int n = array.length-1;
 415  0
             float[] change = new float[n];
 416  0
             for(int i=0; i<n; i++)change[i] = (array[i+1] - array[i])*100.0F/array[i];
 417  0
             return Stat.standardDeviation(change);
 418  
         }
 419  
 
 420  
         // Coefficient of variation of an array of doubles
 421  
         public static double coefficientOfVariation(double[] array){
 422  0
             return 100.0D*Stat.standardDeviation(array)/Math.abs(Stat.mean(array));
 423  
         }
 424  
 
 425  
         // Coefficient of variation of an array of float
 426  
         public static float coefficientOfVariation(float[] array){
 427  0
             return 100.0F*Stat.standardDeviation(array)/Math.abs(Stat.mean(array));
 428  
         }
 429  
 
 430  
         // Subtract mean of an array from data array elements
 431  
         public static double[] subtractMean(double[] array){
 432  0
             int n = array.length;
 433  0
             double mean = Stat.mean(array);
 434  0
             double[] arrayMinusMean = new double[n];
 435  0
             for(int i=0; i<n; i++)arrayMinusMean[i] = array[i] - mean;
 436  
 
 437  0
             return arrayMinusMean;
 438  
         }
 439  
 
 440  
         // Subtract mean of an array from data array elements
 441  
         public static float[] subtractMean(float[] array){
 442  0
             int n = array.length;
 443  0
             float mean = Stat.mean(array);
 444  0
             float[] arrayMinusMean = new float[n];
 445  0
             for(int i=0; i<n; i++)arrayMinusMean[i] = array[i] - mean;
 446  
 
 447  0
             return arrayMinusMean;
 448  
         }
 449  
 
 450  
         // Variance of a 1D array of doubles, aa
 451  
         public static double variance(double[] aa){
 452  0
                 int n = aa.length;
 453  0
                 double sum=0.0D, mean=0.0D;
 454  0
                 for(int i=0; i<n; i++){
 455  0
                         sum+=aa[i];
 456  
                 }
 457  0
                 mean=sum/((double)n);
 458  0
                 sum=0.0D;
 459  0
                 for(int i=0; i<n; i++){
 460  0
                         sum+=Fmath.square(aa[i]-mean);
 461  
                 }
 462  0
                 return sum/((double)(n-1));
 463  
         }
 464  
 
 465  
         // Variance of a 1D array of floats, aa
 466  
         public static float variance(float[] aa){
 467  0
                 int n = aa.length;
 468  0
                 float sum=0.0F, mean=0.0F;
 469  0
                 for(int i=0; i<n; i++){
 470  0
                         sum+=aa[i];
 471  
                 }
 472  0
                 mean=sum/((float)n);
 473  0
                 sum=0.0F;
 474  0
                 for(int i=0; i<n; i++){
 475  0
                         sum+=Fmath.square(aa[i]-mean);
 476  
                 }
 477  0
                 return sum/((float)(n-1));
 478  
         }
 479  
 
 480  
        // Variance of a 1D array of int, aa
 481  
         public static double variance(int[] aa){
 482  0
                 int n = aa.length;
 483  0
                 double sum=0.0D, mean=0.0D;
 484  0
                 for(int i=0; i<n; i++){
 485  0
                         sum+=(double)aa[i];
 486  
                 }
 487  0
                 mean=sum/((double)n);
 488  0
                 sum=0.0D;
 489  0
                 for(int i=0; i<n; i++){
 490  0
                         sum+=Fmath.square((double)aa[i]-mean);
 491  
                 }
 492  0
                 return sum/((double)(n-1));
 493  
         }
 494  
 
 495  
        // Variance of a 1D array of ilong, aa
 496  
         public static double variance(long[] aa){
 497  0
                 int n = aa.length;
 498  0
                 double sum=0.0D, mean=0.0D;
 499  0
                 for(int i=0; i<n; i++){
 500  0
                         sum+=(double)aa[i];
 501  
                 }
 502  0
                 mean=sum/((double)n);
 503  0
                 sum=0.0D;
 504  0
                 for(int i=0; i<n; i++){
 505  0
                         sum+=Fmath.square((double)aa[i]-mean);
 506  
                 }
 507  0
                 return sum/((double)(n-1));
 508  
         }
 509  
 
 510  
         // Weighted variance of a 1D array of doubles, aa
 511  
         public static double variance(double[] aa, double[] ww){
 512  0
                 int n = aa.length;
 513  0
                 if(n!=ww.length)throw new IllegalArgumentException("length of variable array, " + n + " and length of weight array, " + ww.length + " are different");
 514  0
                 double sumx=0.0D, sumw=0.0D, mean=0.0D;
 515  0
                 double[] weight = new double[n];
 516  0
                 for(int i=0; i<n; i++){
 517  0
                         sumx+=aa[i];
 518  0
                         weight[i]=1.0D/(ww[i]*ww[i]);
 519  0
                         sumw+=weight[i];
 520  
                 }
 521  0
                 mean=sumx/sumw;
 522  0
                 sumx=0.0D;
 523  0
                 for(int i=0; i<n; i++){
 524  0
                         sumx+=weight[i]*Fmath.square(aa[i]-mean);
 525  
                 }
 526  0
                 return sumx*(double)(n)/((double)(n-1)*sumw);
 527  
         }
 528  
 
 529  
         // Weighted variance of a 1D array of floats, aa
 530  
         public static float variance(float[] aa, float[] ww){
 531  0
                 int n = aa.length;
 532  0
                 if(n!=ww.length)throw new IllegalArgumentException("length of variable array, " + n + " and length of weight array, " + ww.length + " are different");
 533  0
                 float sumx=0.0F, sumw=0.0F, mean=0.0F;
 534  0
                 float[] weight = new float[n];
 535  0
                 for(int i=0; i<n; i++){
 536  0
                         sumx+=aa[i];
 537  0
                         weight[i]=1.0F/(ww[i]*ww[i]);
 538  0
                         sumw+=weight[i];
 539  
                 }
 540  0
                 mean=sumx/sumw;
 541  0
                 sumx=0.0F;
 542  0
                 for(int i=0; i<n; i++){
 543  0
                         sumx+=weight[i]*Fmath.square(aa[i]-mean);
 544  
                 }
 545  0
                 return sumx*(float)(n)/((float)(n-1)*sumw);
 546  
         }
 547  
 
 548  
         // Covariance of two 1D arrays of doubles, xx and yy
 549  
         public static double covariance(double[] xx, double[] yy){
 550  0
                 int n = xx.length;
 551  0
                 if(n!=yy.length)throw new IllegalArgumentException("length of x variable array, " + n + " and length of y array, " + yy.length + " are different");
 552  
 
 553  0
                 double sumx=0.0D, meanx=0.0D;
 554  0
                 double sumy=0.0D, meany=0.0D;
 555  0
                 for(int i=0; i<n; i++){
 556  0
                         sumx+=xx[i];
 557  0
                         sumy+=yy[i];
 558  
                 }
 559  0
                 meanx=sumx/((double)n);
 560  0
                 meany=sumy/((double)n);
 561  0
                 double sum=0.0D;
 562  0
                 for(int i=0; i<n; i++){
 563  0
                         sum+=(xx[i]-meanx)*(yy[i]-meany);
 564  
                 }
 565  0
                 return sum/((double)(n-1));
 566  
         }
 567  
 
 568  
         // Covariance of two 1D arrays of floats, xx and yy
 569  
         public static float covariance(float[] xx, float[] yy){
 570  0
                 int n = xx.length;
 571  0
                 if(n!=yy.length)throw new IllegalArgumentException("length of x variable array, " + n + " and length of y array, " + yy.length + " are different");
 572  
 
 573  0
                 float sumx=0.0F, meanx=0.0F;
 574  0
                 float sumy=0.0F, meany=0.0F;
 575  0
                 for(int i=0; i<n; i++){
 576  0
                         sumx+=xx[i];
 577  0
                         sumy+=yy[i];
 578  
                 }
 579  0
                 meanx=sumx/((float)n);
 580  0
                 meany=sumy/((float)n);
 581  0
                 float sum=0.0F;
 582  0
                 for(int i=0; i<n; i++){
 583  0
                         sum+=(xx[i]-meanx)*(yy[i]-meany);
 584  
                 }
 585  0
                 return sum/((float)(n-1));
 586  
         }
 587  
 
 588  
         // Covariance of two 1D arrays of ints, xx and yy
 589  
         public static double covariance(int[] xx, int[] yy){
 590  0
                 int n = xx.length;
 591  0
                 if(n!=yy.length)throw new IllegalArgumentException("length of x variable array, " + n + " and length of y array, " + yy.length + " are different");
 592  
 
 593  0
                 double sumx=0.0D, meanx=0.0D;
 594  0
                 double sumy=0.0D, meany=0.0D;
 595  0
                 for(int i=0; i<n; i++){
 596  0
                         sumx+=(double)xx[i];
 597  0
                         sumy+=(double)yy[i];
 598  
                 }
 599  0
                 meanx=sumx/((double)n);
 600  0
                 meany=sumy/((double)n);
 601  0
                 double sum=0.0D;
 602  0
                 for(int i=0; i<n; i++){
 603  0
                         sum+=((double)xx[i]-meanx)*((double)yy[i]-meany);
 604  
                 }
 605  0
                 return sum/((double)(n-1));
 606  
         }
 607  
 
 608  
         // Covariance of two 1D arrays of ints, xx and yy
 609  
         public static double covariance(long[] xx, long[] yy){
 610  0
                 int n = xx.length;
 611  0
                 if(n!=yy.length)throw new IllegalArgumentException("length of x variable array, " + n + " and length of y array, " + yy.length + " are different");
 612  
 
 613  0
                 double sumx=0.0D, meanx=0.0D;
 614  0
                 double sumy=0.0D, meany=0.0D;
 615  0
                 for(int i=0; i<n; i++){
 616  0
                         sumx+=(double)xx[i];
 617  0
                         sumy+=(double)yy[i];
 618  
                 }
 619  0
                 meanx=sumx/((double)n);
 620  0
                 meany=sumy/((double)n);
 621  0
                 double sum=0.0D;
 622  0
                 for(int i=0; i<n; i++){
 623  0
                         sum+=((double)xx[i]-meanx)*((double)yy[i]-meany);
 624  
                 }
 625  0
                 return sum/((double)(n-1));
 626  
         }
 627  
 
 628  
         // Weighted covariance of two 1D arrays of doubles, xx and yy with weights ww
 629  
         public static double covariance(double[] xx, double[] yy, double[] ww){
 630  0
                 int n = xx.length;
 631  0
                 if(n!=yy.length)throw new IllegalArgumentException("length of x variable array, " + n + " and length of y array, " + yy.length + " are different");
 632  0
                 if(n!=ww.length)throw new IllegalArgumentException("length of x variable array, " + n + " and length of weight array, " + yy.length + " are different");
 633  0
                 double sumx=0.0D, sumy=0.0D, sumw=0.0D, meanx=0.0D, meany=0.0D;
 634  0
                 double[] weight = new double[n];
 635  0
                 for(int i=0; i<n; i++){
 636  0
                         sumx+=xx[i];
 637  0
                         sumy+=yy[i];
 638  0
                         weight[i]=1.0D/(ww[i]*ww[i]);
 639  0
                         sumw+=weight[i];
 640  
                 }
 641  0
                 meanx=sumx/sumw;
 642  0
                 meany=sumy/sumw;
 643  
 
 644  0
                 double sum=0.0D;
 645  0
                 for(int i=0; i<n; i++){
 646  0
                         sum+=weight[i]*(xx[i]-meanx)*(yy[i]-meany);
 647  
                 }
 648  0
                 return sum*(double)(n)/((double)(n-1)*sumw);
 649  
         }
 650  
 
 651  
         //
 652  
 
 653  
         // Gamma function
 654  
         // Lanczos approximation (6 terms)
 655  
         public static double gamma(double x){
 656  
 
 657  0
                 double xcopy = x;
 658  0
                 double first = x + lgfGamma + 0.5;
 659  0
                 double second = lgfCoeff[0];
 660  0
                 double fg = 0.0D;
 661  
 
 662  0
                 if(x>=0.0){
 663  0
                         if(x>=1.0D && x-(int)x==0.0D){
 664  0
                                 fg = Stat.factorial(x)/x;
 665  
                         }
 666  
                         else{
 667  0
                                 first = Math.pow(first, x + 0.5)*Math.exp(-first);
 668  0
                                 for(int i=1; i<=lgfN; i++)second += lgfCoeff[i]/++xcopy;
 669  0
                                 fg = first*Math.sqrt(2.0*Math.PI)*second/x;
 670  
                         }
 671  
                 }
 672  
                 else{
 673  0
                          fg = -Math.PI/(x*Stat.gamma(-x)*Math.sin(Math.PI*x));
 674  
                 }
 675  0
                 return fg;
 676  
         }
 677  
 
 678  
         // Return the Lanczos constant gamma
 679  
         public static double getLanczosGamma(){
 680  0
                 return Stat.lgfGamma;
 681  
         }
 682  
 
 683  
         // Return the Lanczos constant N (number of coeeficients + 1)
 684  
         public static int getLanczosN(){
 685  0
                 return Stat.lgfN;
 686  
         }
 687  
 
 688  
         // Return the Lanczos coeeficients
 689  
         public static double[] getLanczosCoeff(){
 690  0
                 int n = Stat.getLanczosN()+1;
 691  0
                 double[] coef = new double[n];
 692  0
                 for(int i=0; i<n; i++){
 693  0
                         coef[i] = Stat.lgfCoeff[i];
 694  
                 }
 695  0
                 return coef;
 696  
         }
 697  
 
 698  
         // Return the nearest smallest representable floating point number to zero with mantissa rounded to 1.0
 699  
         public static double getFpmin(){
 700  0
                 return Stat.FPMIN;
 701  
         }
 702  
 
 703  
         // log to base e of the Gamma function
 704  
         // Lanczos approximation (6 terms)
 705  
         public static double logGamma(double x){
 706  0
                 double xcopy = x;
 707  0
                 double fg = 0.0D;
 708  0
                 double first = x + lgfGamma + 0.5;
 709  0
                 double second = lgfCoeff[0];
 710  
 
 711  0
                 if(x>=0.0){
 712  0
                         if(x>=1.0 && x-(int)x==0.0){
 713  0
                                 fg = Stat.logFactorial(x)-Math.log(x);
 714  
                         }
 715  
                         else{
 716  0
                                 first -= (x + 0.5)*Math.log(first);
 717  0
                                 for(int i=1; i<=lgfN; i++)second += lgfCoeff[i]/++xcopy;
 718  0
                                 fg = Math.log(Math.sqrt(2.0*Math.PI)*second/x) - first;
 719  
                         }
 720  
                 }
 721  
                 else{
 722  0
                         fg = Math.PI/(Stat.gamma(1.0D-x)*Math.sin(Math.PI*x));
 723  
 
 724  0
                         if(fg!=1.0/0.0 && fg!=-1.0/0.0){
 725  0
                                 if(fg<0){
 726  0
                                          throw new IllegalArgumentException("\nThe gamma function is negative");
 727  
                                 }
 728  
                                 else{
 729  0
                                         fg = Math.log(fg);
 730  
                                 }
 731  
                         }
 732  
                 }
 733  0
                 return fg;
 734  
         }
 735  
 
 736  
         // Regularised Incomplete Gamma Function P(a,x) = integral from zero to x of (exp(-t)t^(a-1))dt
 737  
         public static double incompleteGamma(double a, double x){
 738  0
                 if(a<0.0D  || x<0.0D)throw new IllegalArgumentException("\nFunction defined only for a >= 0 and x>=0");
 739  0
                 double igf = 0.0D;
 740  
 
 741  0
                 if(x < a+1.0D){
 742  
                         // Series representation
 743  0
                         igf = incompleteGammaSer(a, x);
 744  
                 }
 745  
                 else{
 746  
                         // Continued fraction representation
 747  0
                         igf = incompleteGammaFract(a, x);
 748  
                 }
 749  0
                 return igf;
 750  
         }
 751  
 
 752  
         // Complementary Incomplete Gamma Function Q(a,x) = 1 - P(a,x) = 1 - integral from zero to x of (exp(-t)t^(a-1))dt
 753  
         // Also known as the Incomplete Gamma Function
 754  
         public static double incompleteGammaComplementary(double a, double x){
 755  0
                 if(a<0.0D  || x<0.0D)throw new IllegalArgumentException("\nFunction defined only for a >= 0 and x>=0");
 756  0
                 double igf = 0.0D;
 757  
 
 758  0
                 if(x!=0.0D){
 759  0
                         if(x==1.0D/0.0D)
 760  
                         {
 761  0
                                 igf=1.0D;
 762  
                         }
 763  
                         else{
 764  0
                                 if(x < a+1.0D){
 765  
                                         // Series representation
 766  0
                                         igf = 1.0D - incompleteGammaSer(a, x);
 767  
                                 }
 768  
                                 else{
 769  
                                         // Continued fraction representation
 770  0
                                         igf = 1.0D - incompleteGammaFract(a, x);
 771  
                                 }
 772  
                         }
 773  
                 }
 774  0
                 return igf;
 775  
         }
 776  
 
 777  
         // Regularised Incomplete Gamma Function P(a,x) = integral from zero to x of (exp(-t)t^(a-1))dt
 778  
         // Series representation of the function - valid for x < a + 1
 779  
         public static double incompleteGammaSer(double a, double x){
 780  0
                 if(a<0.0D  || x<0.0D)throw new IllegalArgumentException("\nFunction defined only for a >= 0 and x>=0");
 781  0
                 if(x>=a+1) throw new IllegalArgumentException("\nx >= a+1   use Continued Fraction Representation");
 782  
 
 783  0
                 int i = 0;
 784  0
                 double igf = 0.0D;
 785  0
                 boolean check = true;
 786  
 
 787  0
                 double acopy = a;
 788  0
                 double sum = 1.0/a;
 789  0
                 double incr = sum;
 790  0
                 double loggamma = Stat.logGamma(a);
 791  
 
 792  0
                 while(check){
 793  0
                         ++i;
 794  0
                         ++a;
 795  0
                         incr *= x/a;
 796  0
                         sum += incr;
 797  0
                         if(Math.abs(incr) < Math.abs(sum)*Stat.igfeps){
 798  0
                                 igf = sum*Math.exp(-x+acopy*Math.log(x)- loggamma);
 799  0
                                 check = false;
 800  
                         }
 801  0
                         if(i>=Stat.igfiter){
 802  0
                                 check=false;
 803  0
                                 igf = sum*Math.exp(-x+acopy*Math.log(x)- loggamma);
 804  0
                                 System.out.println("\nMaximum number of iterations were exceeded in Stat.incompleteGammaSer().\nCurrent value returned.\nIncrement = "+String.valueOf(incr)+".\nSum = "+String.valueOf(sum)+".\nTolerance =  "+String.valueOf(igfeps));
 805  
                         }
 806  
                 }
 807  0
                 return igf;
 808  
         }
 809  
 
 810  
         // Regularised Incomplete Gamma Function P(a,x) = integral from zero to x of (exp(-t)t^(a-1))dt
 811  
         // Continued Fraction representation of the function - valid for x >= a + 1
 812  
         // This method follows the general procedure used in Numerical Recipes for C,
 813  
         // The Art of Scientific Computing
 814  
         // by W H Press, S A Teukolsky, W T Vetterling & B P Flannery
 815  
         // Cambridge University Press,   http://www.nr.com/
 816  
         public static double incompleteGammaFract(double a, double x){
 817  0
                 if(a<0.0D  || x<0.0D)throw new IllegalArgumentException("\nFunction defined only for a >= 0 and x>=0");
 818  0
                 if(x<a+1) throw new IllegalArgumentException("\nx < a+1   Use Series Representation");
 819  
 
 820  0
                 int i = 0;
 821  0
                 double ii = 0;
 822  0
                 double igf = 0.0D;
 823  0
                 boolean check = true;
 824  
 
 825  0
                 double loggamma = Stat.logGamma(a);
 826  0
                 double numer = 0.0D;
 827  0
                 double incr = 0.0D;
 828  0
                 double denom = x - a + 1.0D;
 829  0
                 double first = 1.0D/denom;
 830  0
                 double term = 1.0D/FPMIN;
 831  0
                 double prod = first;
 832  
 
 833  0
                 while(check){
 834  0
                         ++i;
 835  0
                         ii = (double)i;
 836  0
                         numer = -ii*(ii - a);
 837  0
                         denom += 2.0D;
 838  0
                         first = numer*first + denom;
 839  0
                         if(Math.abs(first) < Stat.FPMIN){
 840  0
                             first = Stat.FPMIN;
 841  
                         }
 842  0
                         term = denom + numer/term;
 843  0
                         if(Math.abs(term) < Stat.FPMIN){
 844  0
                             term = Stat.FPMIN;
 845  
                          }
 846  0
                         first = 1.0D/first;
 847  0
                         incr = first*term;
 848  0
                         prod *= incr;
 849  0
                         if(Math.abs(incr - 1.0D) < igfeps)check = false;
 850  0
                         if(i>=Stat.igfiter){
 851  0
                                 check=false;
 852  0
                                 System.out.println("\nMaximum number of iterations were exceeded in Stat.incompleteGammaFract().\nCurrent value returned.\nIncrement - 1 = "+String.valueOf(incr-1)+".\nTolerance =  "+String.valueOf(igfeps));
 853  
                         }
 854  
                 }
 855  0
                 igf = 1.0D - Math.exp(-x+a*Math.log(x)-loggamma)*prod;
 856  0
                 return igf;
 857  
         }
 858  
 
 859  
         // Reset the maximum number of iterations allowed in the calculation of the incomplete gamma functions
 860  
         public static void setIncGammaMaxIter(int igfiter){
 861  0
                 Stat.igfiter=igfiter;
 862  0
         }
 863  
 
 864  
         // Return the maximum number of iterations allowed in the calculation of the incomplete gamma functions
 865  
         public static int getIncGammaMaxIter(){
 866  0
                 return Stat.igfiter;
 867  
         }
 868  
 
 869  
         // Reset the tolerance used in the calculation of the incomplete gamma functions
 870  
         public static void setIncGammaTol(double igfeps){
 871  0
                 Stat.igfeps=igfeps;
 872  0
         }
 873  
 
 874  
         // Return the tolerance used in the calculation of the incomplete gamm functions
 875  
         public static double getIncGammaTol(){
 876  0
                 return Stat.igfeps;
 877  
         }
 878  
 
 879  
         // Beta function
 880  
         public static double beta(double z, double w){
 881  0
                 return Math.exp(logGamma(z) + logGamma(w) - logGamma(z + w));
 882  
         }
 883  
 
 884  
         // Regularised Incomplete Beta function
 885  
         // Continued Fraction approximation (see Numerical recipies for details of method)
 886  
         public static double incompleteBeta(double z, double w, double x){
 887  0
             if(x<0.0D || x>1.0D)throw new IllegalArgumentException("Argument x, "+x+", must be lie between 0 and 1 (inclusive)");
 888  0
             double ibeta = 0.0D;
 889  0
             if(x==0.0D){
 890  0
                 ibeta=0.0D;
 891  
             }
 892  
             else{
 893  0
                 if(x==1.0D){
 894  0
                     ibeta=1.0D;
 895  
                 }
 896  
                 else{
 897  
                     // Term before continued fraction
 898  0
                     ibeta = Math.exp(Stat.logGamma(z+w) - Stat.logGamma(z) - logGamma(w) + z*Math.log(x) + w*Math.log(1.0D-x));
 899  
                     // Continued fraction
 900  0
                     if(x < (z+1.0D)/(z+w+2.0D)){
 901  0
                         ibeta = ibeta*Stat.contFract(z, w, x)/z;
 902  
                     }
 903  
                     else{
 904  
                         // Use symmetry relationship
 905  0
                         ibeta = 1.0D - ibeta*Stat.contFract(w, z, 1.0D-x)/w;
 906  
                     }
 907  
                 }
 908  
             }
 909  0
             return ibeta;
 910  
         }
 911  
 
 912  
         // Incomplete fraction summation used in the method incompleteBeta
 913  
         // modified Lentz's method
 914  
         public static double contFract(double a, double b, double x){
 915  0
             int maxit = 500;
 916  0
             double eps = 3.0e-7;
 917  0
             double aplusb = a + b;
 918  0
             double aplus1 = a + 1.0D;
 919  0
             double aminus1 = a - 1.0D;
 920  0
             double c = 1.0D;
 921  0
             double d = 1.0D - aplusb*x/aplus1;
 922  0
             if(Math.abs(d)<Stat.FPMIN)d = FPMIN;
 923  0
             d = 1.0D/d;
 924  0
             double h = d;
 925  0
             double aa = 0.0D;
 926  0
             double del = 0.0D;
 927  0
             int i=1, i2=0;
 928  0
             boolean test=true;
 929  0
             while(test){
 930  0
                 i2=2*i;
 931  0
                 aa = i*(b-i)*x/((aminus1+i2)*(a+i2));
 932  0
                 d = 1.0D + aa*d;
 933  0
                 if(Math.abs(d)<Stat.FPMIN)d = FPMIN;
 934  0
                 c = 1.0D + aa/c;
 935  0
                 if(Math.abs(c)<Stat.FPMIN)c = FPMIN;
 936  0
                 d = 1.0D/d;
 937  0
                 h *= d*c;
 938  0
                 aa = -(a+i)*(aplusb+i)*x/((a+i2)*(aplus1+i2));
 939  0
                 d = 1.0D + aa*d;
 940  0
                 if(Math.abs(d)<Stat.FPMIN)d = FPMIN;
 941  0
                 c = 1.0D + aa/c;
 942  0
                 if(Math.abs(c)<Stat.FPMIN)c = FPMIN;
 943  0
                 d = 1.0D/d;
 944  0
                 del = d*c;
 945  0
                 h *= del;
 946  0
                 i++;
 947  0
                 if(Math.abs(del-1.0D) < eps)test=false;
 948  0
                 if(i>maxit){
 949  0
                     test=false;
 950  0
                     System.out.println("Maximum number of iterations ("+maxit+") exceeded in Stat.contFract in Stat.incomplete Beta");
 951  
                 }
 952  
             }
 953  0
             return h;
 954  
 
 955  
         }
 956  
 
 957  
         // Error Function
 958  
         public static double erf(double x){
 959  0
                 double erf = 0.0D;
 960  0
                 if(x!=0.0){
 961  0
                         if(x==1.0D/0.0D){
 962  0
                                 erf = 1.0D;
 963  
                         }
 964  
                         else{
 965  0
                                 if(x>=0){
 966  0
                                         erf = Stat.incompleteGamma(0.5, x*x);
 967  
                                 }
 968  
                                 else{
 969  0
                                         erf = -Stat.incompleteGamma(0.5, x*x);
 970  
                                 }
 971  
                         }
 972  
                 }
 973  0
                 return erf;
 974  
         }
 975  
 
 976  
         // Complementary Error Function
 977  
         public static double erfc(double x){
 978  0
                 double erfc = 1.0D;
 979  0
                 if(x!=0.0){
 980  0
                         if(x==1.0D/0.0D){
 981  0
                                 erfc = 0.0D;
 982  
                         }
 983  
                         else{
 984  0
                                 if(x>=0){
 985  0
                                         erfc = 1.0D - Stat.incompleteGamma(0.5, x*x);
 986  
                                 }
 987  
                                 else{
 988  0
                                         erfc = 1.0D + Stat.incompleteGamma(0.5, x*x);
 989  
                                 }
 990  
                         }
 991  
                 }
 992  0
                 return erfc;
 993  
         }
 994  
 
 995  
         // Gaussian (normal) cumulative distribution function
 996  
         // probability that a variate will assume a value less than the upperlimit
 997  
         // mean  =  the mean, sd = standard deviation
 998  
         public static double normalProb(double mean, double sd, double upperlimit){
 999  0
                 double arg = (upperlimit - mean)/(sd*Math.sqrt(2.0));
 1000  0
                 return (1.0D + Stat.erf(arg))/2.0D;
 1001  
         }
 1002  
 
 1003  
         // Gaussian (normal) cumulative distribution function
 1004  
         // probability that a variate will assume a value less than the upperlimit
 1005  
         // mean  =  the mean, sd = standard deviation
 1006  
         public static double gaussianProb(double mean, double sd, double upperlimit){
 1007  0
                 double arg = (upperlimit - mean)/(sd*Math.sqrt(2.0));
 1008  0
                 return (1.0D + Stat.erf(arg))/2.0D;
 1009  
         }
 1010  
 
 1011  
         // Gaussian (normal) cumulative distribution function
 1012  
         // probability that a variate will assume a value between the lower and  the upper limits
 1013  
         // mean  =  the mean, sd = standard deviation
 1014  
         public static double normalProb(double mean, double sd, double lowerlimit, double upperlimit){
 1015  0
                 double arg1 = (lowerlimit - mean)/(sd*Math.sqrt(2.0));
 1016  0
                 double arg2 = (upperlimit - mean)/(sd*Math.sqrt(2.0));
 1017  
 
 1018  0
                 return (Stat.erf(arg2)-Stat.erf(arg1))/2.0D;
 1019  
         }
 1020  
 
 1021  
         // Gaussian (normal) cumulative distribution function
 1022  
         // probability that a variate will assume a value between the lower and  the upper limits
 1023  
         // mean  =  the mean, sd = standard deviation
 1024  
         public static double gaussianProb(double mean, double sd, double lowerlimit, double upperlimit){
 1025  0
                 double arg1 = (lowerlimit - mean)/(sd*Math.sqrt(2.0));
 1026  0
                 double arg2 = (upperlimit - mean)/(sd*Math.sqrt(2.0));
 1027  
 
 1028  0
                 return (Stat.erf(arg2)-Stat.erf(arg1))/2.0D;
 1029  
         }
 1030  
 
 1031  
         // Gaussian (normal) probability
 1032  
         // mean  =  the mean, sd = standard deviation
 1033  
         public static double normal(double mean, double sd, double x){
 1034  0
                 return Math.exp(-Fmath.square((x - mean)/sd)/2.0)/(sd*Math.sqrt(2.0D*Math.PI));
 1035  
         }
 1036  
 
 1037  
         // Gaussian (normal) probability
 1038  
         // mean  =  the mean, sd = standard deviation
 1039  
         public static double gaussian(double mean, double sd, double x){
 1040  0
                 return Math.exp(-Fmath.square((x - mean)/sd)/2.0)/(sd*Math.sqrt(2.0D*Math.PI));
 1041  
         }
 1042  
 
 1043  
         // Returns an array of Gaussian (normal) random deviates - clock seed
 1044  
         // mean  =  the mean, sd = standard deviation, length of array
 1045  
         public static double[] normalRand(double mean, double sd, int n){
 1046  0
                 double[] ran = new double[n];
 1047  0
                 Random rr = new Random();
 1048  0
                 for(int i=0; i<n; i++){
 1049  0
                     ran[i]=rr.nextGaussian();
 1050  0
                     ran[i] = ran[i]*sd+mean;
 1051  
                 }
 1052  0
                 return ran;
 1053  
         }
 1054  
 
 1055  
         // Returns an array of Gaussian (normal) random deviates - clock seed
 1056  
         // mean  =  the mean, sd = standard deviation, length of array
 1057  
         public static double[] gaussianRand(double mean, double sd, int n){
 1058  0
                 double[] ran = new double[n];
 1059  0
                 Random rr = new Random();
 1060  0
                 for(int i=0; i<n; i++){
 1061  0
                     ran[i]=rr.nextGaussian();
 1062  0
                     ran[i] = ran[i]*sd+mean;
 1063  
                 }
 1064  0
                 return ran;
 1065  
         }
 1066  
 
 1067  
         // Returns an array of Gaussian (normal) random deviates - user provided seed
 1068  
         // mean  =  the mean, sd = standard deviation, length of array
 1069  
         public static double[] normalRand(double mean, double sd, int n, long seed){
 1070  0
                 double[] ran = new double[n];
 1071  0
                 Random rr = new Random(seed);
 1072  0
                 for(int i=0; i<n; i++){
 1073  0
                     ran[i]=rr.nextGaussian();
 1074  0
                     ran[i] = ran[i]*sd+mean;
 1075  
                 }
 1076  0
                 return ran;
 1077  
         }
 1078  
 
 1079  
         // Returns an array of Gaussian (normal) random deviates - user provided seed
 1080  
         // mean  =  the mean, sd = standard deviation, length of array
 1081  
         public static double[] gaussianRand(double mean, double sd, int n, long seed){
 1082  0
                 double[] ran = new double[n];
 1083  0
                 Random rr = new Random(seed);
 1084  0
                 for(int i=0; i<n; i++){
 1085  0
                     ran[i]=rr.nextGaussian();
 1086  0
                     ran[i] = ran[i]*sd+mean;
 1087  
                 }
 1088  0
                 return ran;
 1089  
         }
 1090  
 
 1091  
 
 1092  
 
 1093  
         // Logistic cumulative distribution function
 1094  
         // probability that a variate will assume a value less than the upperlimit
 1095  
         // mu  =  location parameter, beta = scale parameter
 1096  
         public static double logisticProb(double mu, double beta, double upperlimit){
 1097  0
                 return 0.5D*(1.0D + Math.tanh((upperlimit - mu)/(2.0D*beta)));
 1098  
         }
 1099  
 
 1100  
 
 1101  
         // Logistic cumulative distribution function
 1102  
         // probability that a variate will assume a value between the lower and  the upper limits
 1103  
         // mu  =  location parameter, beta = scale parameter
 1104  
         public static double logisticProb(double mu, double beta, double lowerlimit, double upperlimit){
 1105  0
                 double arg1 = 0.5D*(1.0D + Math.tanh((lowerlimit - mu)/(2.0D*beta)));
 1106  0
                 double arg2 = 0.5D*(1.0D + Math.tanh((upperlimit - mu)/(2.0D*beta)));
 1107  0
                 return arg2 - arg1;
 1108  
         }
 1109  
 
 1110  
         // Logistic probability density function
 1111  
         // mu  =  location parameter, beta = scale parameter
 1112  
         public static double logistic(double mu, double beta, double x){
 1113  0
                 return Fmath.square(Fmath.sech((x - mu)/(2.0D*beta)))/(4.0D*beta);
 1114  
         }
 1115  
 
 1116  
         // Returns an array of logistic distribution random deviates - clock seed
 1117  
         // mu  =  location parameter, beta = scale parameter
 1118  
         public static double[] logisticRand(double mu, double beta, int n){
 1119  0
                 double[] ran = new double[n];
 1120  0
                 Random rr = new Random();
 1121  0
                 for(int i=0; i<n; i++){
 1122  0
                     ran[i] = 2.0D*beta*Fmath.atanh(2.0D*rr.nextDouble() - 1.0D) + mu;
 1123  
                 }
 1124  0
                 return ran;
 1125  
         }
 1126  
 
 1127  
         // Returns an array of Gaussian (normal) random deviates - user provided seed
 1128  
         // mean  =  the mean, sd = standard deviation, length of array
 1129  
         public static double[] logisticRand(double mu, double beta, int n, long seed){
 1130  0
                 double[] ran = new double[n];
 1131  0
                 Random rr = new Random(seed);
 1132  0
                 for(int i=0; i<n; i++){
 1133  0
                     ran[i] = 2.0D*beta*Fmath.atanh(2.0D*rr.nextDouble() - 1.0D) + mu;
 1134  
                 }
 1135  0
                 return ran;
 1136  
         }
 1137  
 
 1138  
         // Logistic distribution mean
 1139  
         public static double logisticMean(double mu){
 1140  0
                 return mu;
 1141  
         }
 1142  
 
 1143  
 
 1144  
         // Logistic distribution standard deviation
 1145  
         public static double logisticStandDev(double beta){
 1146  0
                 return Math.sqrt(Fmath.square(Math.PI*beta)/3.0D);
 1147  
         }
 1148  
 
 1149  
         // Logistic distribution mode
 1150  
         public static double logisticMode(double mu){
 1151  0
                 return mu;
 1152  
         }
 1153  
 
 1154  
         // Logistic distribution median
 1155  
         public static double logisticMedian(double mu){
 1156  0
                 return mu;
 1157  
         }
 1158  
 
 1159  
         // Lorentzian cumulative distribution function
 1160  
         // probability that a variate will assume a value less than the upperlimit
 1161  
         public static double lorentzianProb(double mu, double gamma, double upperlimit){
 1162  0
                 double arg = (upperlimit - mu)/(gamma/2.0D);
 1163  0
                 return (1.0D/Math.PI)*(Math.atan(arg)+Math.PI/2.0);
 1164  
         }
 1165  
 
 1166  
         // Lorentzian cumulative distribution function
 1167  
         // probability that a variate will assume a value between the lower and  the upper limits
 1168  
         public static double lorentzianProb(double mu, double gamma, double lowerlimit, double upperlimit){
 1169  0
                 double arg1 = (upperlimit - mu)/(gamma/2.0D);
 1170  0
                 double arg2 = (lowerlimit - mu)/(gamma/2.0D);
 1171  0
                 return (1.0D/Math.PI)*(Math.atan(arg1)-Math.atan(arg2));
 1172  
         }
 1173  
 
 1174  
         // Cumulative Poisson Probability Function
 1175  
         // probability that a number of Poisson random events will occur between 0 and k (inclusive)
 1176  
         // k is an integer greater than equal to 1
 1177  
         // mean  = mean of the Poisson distribution
 1178  
         public static double poissonProb(int k, double mean){
 1179  0
                 if(k<1)throw new IllegalArgumentException("k must be an integer greater than or equal to 1");
 1180  0
                 return Stat.incompleteGammaComplementary((double) k, mean);
 1181  
         }
 1182  
 
 1183  
         // Poisson Probability Function
 1184  
         // k is an integer greater than or equal to zero
 1185  
         // mean  = mean of the Poisson distribution
 1186  
         public static double poisson(int k, double mean){
 1187  0
                 if(k<0)throw new IllegalArgumentException("k must be an integer greater than or equal to 0");
 1188  0
                 return Math.pow(mean, k)*Math.exp(-mean)/Stat.factorial((double)k);
 1189  
         }
 1190  
 
 1191  
         // Returns an array of Poisson random deviates - clock seed
 1192  
         // mean  =  the mean,  n = length of array
 1193  
         // follows the ideas of Numerical Recipes
 1194  
         public static double[] poissonRand(double mean, int n){
 1195  
 
 1196  0
                 Random rr = new Random();
 1197  0
                 double[] ran = poissonRandCalc(rr, mean, n);
 1198  0
                 return ran;
 1199  
         }
 1200  
 
 1201  
         // Returns an array of Poisson random deviates - user provided seed
 1202  
         // mean  =  the mean,  n = length of array
 1203  
         // follows the ideas of Numerical Recipes
 1204  
         public static double[] poissonRand(double mean, int n, long seed){
 1205  
 
 1206  0
                 Random rr = new Random(seed);
 1207  0
                 double[] ran = poissonRandCalc(rr, mean, n);
 1208  0
                 return ran;
 1209  
         }
 1210  
 
 1211  
         // Calculates and returns an array of Poisson random deviates
 1212  
         private static double[] poissonRandCalc(Random rr, double mean, int n){
 1213  0
                 double[] ran = new double[n];
 1214  0
                 double oldm = -1.0D;
 1215  0
                 double expt = 0.0D;
 1216  0
                 double em = 0.0D;
 1217  0
                 double term = 0.0D;
 1218  0
                 double sq = 0.0D;
 1219  0
                 double lnMean = 0.0D;
 1220  0
                 double yDev = 0.0D;
 1221  
 
 1222  0
                 if(mean < 12.0D){
 1223  0
                     for(int i=0; i<n; i++){
 1224  0
                         if(mean != oldm){
 1225  0
                             oldm = mean;
 1226  0
                             expt = Math.exp(-mean);
 1227  
                         }
 1228  0
                         em = -1.0D;
 1229  0
                         term = 1.0D;
 1230  
                         do{
 1231  0
                             ++em;
 1232  0
                             term *= rr.nextDouble();
 1233  0
                         }while(term>expt);
 1234  0
                         ran[i] = em;
 1235  
                     }
 1236  
                 }
 1237  
                 else{
 1238  0
                     for(int i=0; i<n; i++){
 1239  0
                         if(mean != oldm){
 1240  0
                             oldm = mean;
 1241  0
                             sq = Math.sqrt(2.0D*mean);
 1242  0
                             lnMean = Math.log(mean);
 1243  0
                             expt = lnMean - Stat.logGamma(mean+1.0D);
 1244  
                         }
 1245  
                         do{
 1246  
                             do{
 1247  0
                                 yDev = Math.tan(Math.PI*rr.nextDouble());
 1248  0
                                 em = sq*yDev+mean;
 1249  0
                             }while(em<0.0D);
 1250  0
                             em = Math.floor(em);
 1251  0
                             term = 0.9D*(1.0D+yDev*yDev)*Math.exp(em*lnMean - Stat.logGamma(em+1.0D)-expt);
 1252  0
                         }while(rr.nextDouble()>term);
 1253  0
                         ran[i] = em;
 1254  
                     }
 1255  
                 }
 1256  0
                 return ran;
 1257  
         }
 1258  
 
 1259  
 
 1260  
         // Chi-Square Probability Function
 1261  
         // probability that an observed chi-square value for a correct model should be less than chiSquare
 1262  
         // nu  =  the degrees of freedom
 1263  
         public static double chiSquareProb(double chiSquare, int nu){
 1264  0
                 return Stat.incompleteGamma((double)nu/2.0D, chiSquare/2.0D);
 1265  
         }
 1266  
 
 1267  
         // Chi-Square Statistic for Poisson distribution
 1268  
         public static double chiSquare(double[] observed, double[] expected, double[] variance){
 1269  0
             int nObs = observed.length;
 1270  0
             int nExp = expected.length;
 1271  0
             int nVar = variance.length;
 1272  0
             if(nObs!=nExp)throw new IllegalArgumentException("observed array length does not equal the expected array length");
 1273  0
             if(nObs!=nVar)throw new IllegalArgumentException("observed array length does not equal the variance array length");
 1274  0
             double chi = 0.0D;
 1275  0
             for(int i=0; i<nObs; i++){
 1276  0
                 chi += Fmath.square(observed[i]-expected[i])/variance[i];
 1277  
             }
 1278  0
             return chi;
 1279  
         }
 1280  
 
 1281  
         // Chi-Square Statistic for Poisson distribution for frequency data
 1282  
         // and Poisson distribution for each bin
 1283  
         // double arguments
 1284  
         public static double chiSquareFreq(double[] observedFreq, double[] expectedFreq){
 1285  0
             int nObs = observedFreq.length;
 1286  0
             int nExp = expectedFreq.length;
 1287  0
             if(nObs!=nExp)throw new IllegalArgumentException("observed array length does not equal the expected array length");
 1288  0
             double chi = 0.0D;
 1289  0
             for(int i=0; i<nObs; i++){
 1290  0
                 chi += Fmath.square(observedFreq[i]-expectedFreq[i])/expectedFreq[i];
 1291  
             }
 1292  0
             return chi;
 1293  
         }
 1294  
 
 1295  
         // Chi-Square Statistic for Poisson distribution for frequency data
 1296  
         // and Poisson distribution for each bin
 1297  
         // int arguments
 1298  
         public static double chiSquareFreq(int[] observedFreq, int[] expectedFreq){
 1299  0
             int nObs = observedFreq.length;
 1300  0
             int nExp = expectedFreq.length;
 1301  0
             if(nObs!=nExp)throw new IllegalArgumentException("observed array length does not equal the expected array length");
 1302  0
             double[] observ = new double[nObs];
 1303  0
             double[] expect = new double[nObs];
 1304  0
             for(int i=0; i<nObs; i++){
 1305  0
                 observ[i] = (int)observedFreq[i];
 1306  0
                 expect[i] = (int)expectedFreq[i];
 1307  
             }
 1308  
 
 1309  0
             return chiSquareFreq(observ, expect);
 1310  
         }
 1311  
 
 1312  
         // Returns the binomial cumulative probabilty
 1313  
         public static double binomialProb(double p, int n, int k){
 1314  0
                 if(p<0.0D || p>1.0D)throw new IllegalArgumentException("\np must lie between 0 and 1");
 1315  0
                 if(k<0 || n<0)throw new IllegalArgumentException("\nn and k must be greater than or equal to zero");
 1316  0
                 if(k>n)throw new IllegalArgumentException("\nk is greater than n");
 1317  0
                 return Stat.incompleteBeta(k, n-k+1, p);
 1318  
         }
 1319  
 
 1320  
         // Returns a binomial mass probabilty function
 1321  
         public static double binomial(double p, int n, int k){
 1322  0
                 if(k<0 || n<0)throw new IllegalArgumentException("\nn and k must be greater than or equal to zero");
 1323  0
                 if(k>n)throw new IllegalArgumentException("\nk is greater than n");
 1324  0
                 return Math.floor(0.5D + Math.exp(Stat.logFactorial(n) - Stat.logFactorial(k) - Stat.logFactorial(n-k)))*Math.pow(p, k)*Math.pow(1.0D - p, n - k);
 1325  
         }
 1326  
 
 1327  
         // Returns a binomial Coefficient as a double
 1328  
         public static double binomialCoeff(int n, int k){
 1329  0
                 if(k<0 || n<0)throw new IllegalArgumentException("\nn and k must be greater than or equal to zero");
 1330  0
                 if(k>n)throw new IllegalArgumentException("\nk is greater than n");
 1331  0
                 return Math.floor(0.5D + Math.exp(Stat.logFactorial(n) - Stat.logFactorial(k) - Stat.logFactorial(n-k)));
 1332  
         }
 1333  
 
 1334  
         // Returns an array of n Binomial pseudorandom deviates from a binomial
 1335  
         //  distribution of nTrial trials each of probablity, prob,
 1336  
         //  after         bndlev         Numerical Recipes in C - W.H. Press et al. (Cambridge)
 1337  
         //                            2nd edition 1992 p295.
 1338  
         public double[] binomialRand(double prob, int nTrials, int n){
 1339  
 
 1340  0
             if(nTrials<n)throw new IllegalArgumentException("Number of deviates requested, " + n + ", must be less than the number of trials, " + nTrials);
 1341  0
             if(prob<0.0D || prob>1.0D)throw new IllegalArgumentException("The probablity provided, " + prob + ", must lie between 0 and 1)");
 1342  
 
 1343  0
             double[] ran = new double[n];                   // array of deviates to be returned
 1344  0
             Random rr = new Random();                       // instance of Random
 1345  
 
 1346  0
                 double binomialDeviate = 0.0D;                  // the binomial deviate to be returned
 1347  0
                 double deviateMean = 0.0D;                      // mean of deviate to be produced
 1348  0
                 double testDeviate = 0.0D;                      // test deviate
 1349  0
                 double workingProb = 0.0;                       // working value of the probability
 1350  0
                 double logProb = 0.0;                           // working value of the probability
 1351  0
                 double probOld = -1.0D;                         // previous value of the working probability
 1352  0
                 double probC = -1.0D;                           // complementary value of the working probability
 1353  0
                 double logProbC = -1.0D;                        // log of the complementary value of the working probability
 1354  0
                 int nOld= -1;                                   // previous value of trials counter
 1355  0
                 double enTrials = 0.0D;                         // (double) trials counter
 1356  0
                 double oldGamma = 0.0D;                         // a previous log Gamma function value
 1357  0
                 double tanW = 0.0D;                             // a working tangent
 1358  0
                 double hold0 = 0.0D;                            // a working holding variable
 1359  
                 int jj;                                         // counter
 1360  
 
 1361  0
             double probOriginalValue = prob;
 1362  0
             for(int i=0; i<n; i++){
 1363  0
                 prob = probOriginalValue;
 1364  0
                     workingProb=(prob <= 0.5D ? prob : 1.0-prob);    // distribution invariant on swapping prob for 1 - prob
 1365  0
                     deviateMean = nTrials*workingProb;
 1366  
 
 1367  0
                     if(nTrials < 25) {
 1368  
                         // if number of trials greater than 25 use direct method
 1369  0
                             binomialDeviate=0.0D;
 1370  0
                             for(jj=1;jj<=nTrials;jj++)if (rr.nextDouble() < workingProb) ++binomialDeviate;
 1371  
                     }
 1372  0
                     else if(deviateMean < 1.0D) {
 1373  
                         // if fewer than 1 out of 25 events - Poisson approximation is accurate
 1374  0
                             double expOfMean=Math.exp(-deviateMean);
 1375  0
                             testDeviate=1.0D;
 1376  0
                             for (jj=0;jj<=nTrials;jj++) {
 1377  0
                                     testDeviate *= rr.nextDouble();
 1378  0
                                     if (testDeviate < expOfMean) break;
 1379  
                             }
 1380  0
                             binomialDeviate=(jj <= nTrials ? jj : nTrials);
 1381  
 
 1382  0
                     }
 1383  
                     else{
 1384  
                         // use rejection method
 1385  0
                             if(nTrials != nOld) {
 1386  
                                 // if nTrials has changed compute useful quantities
 1387  0
                                     enTrials = (double)nTrials;
 1388  0
                                     oldGamma = Stat.logGamma(enTrials + 1.0D);
 1389  0
                                     nOld = nTrials;
 1390  
                             }
 1391  0
                             if(workingProb != probOld) {
 1392  
                                 // if workingProb has changed compute useful quantities
 1393  0
                         probC = 1.0 - workingProb;
 1394  0
                                     logProb = Math.log(workingProb);
 1395  0
                                     logProbC = Math.log(probC);
 1396  0
                                     probOld = workingProb;
 1397  
                             }
 1398  
 
 1399  0
                             double sq = Math.sqrt(2.0*deviateMean*probC);
 1400  
                             do{
 1401  
                                     do{
 1402  0
                                             double angle = Math.PI*rr.nextDouble();
 1403  0
                                             tanW = Math.tan(angle);
 1404  0
                                             hold0 = sq*tanW + deviateMean;
 1405  0
                                     }while(hold0 < 0.0D || hold0 >= (enTrials + 1.0D));   //rejection test
 1406  0
                                     hold0 = Math.floor(hold0);                              // integer value distribution
 1407  0
                                     testDeviate = 1.2D*sq*(1.0D + tanW*tanW)*Math.exp(oldGamma - Stat.logGamma(hold0 + 1.0D) - Stat.logGamma(enTrials - hold0 + 1.0D) + hold0*logProb + (enTrials - hold0)*logProbC);
 1408  0
                             }while(rr.nextDouble() > testDeviate);                         // rejection test
 1409  0
                             binomialDeviate=hold0;
 1410  
                     }
 1411  
 
 1412  0
                     if(workingProb != prob) binomialDeviate = nTrials - binomialDeviate;       // symmetry transformation
 1413  
 
 1414  0
                     ran[i] = binomialDeviate;
 1415  
                 }
 1416  
 
 1417  0
                 return ran;
 1418  
         }
 1419  
 
 1420  
         // Returns the F-distribution probabilty for degrees of freedom df1, df2
 1421  
         // F ratio provided
 1422  
         public static double fTestProb(double fValue, int df1, int df2){
 1423  0
             double ddf1 = (double)df1;
 1424  0
             double ddf2 = (double)df2;
 1425  0
             double x = ddf2/(ddf2+ddf1*fValue);
 1426  0
             return Stat.incompleteBeta(df2/2.0D, df1/2.0D, x);
 1427  
         }
 1428  
 
 1429  
         // Returns the F-distribution probabilty for degrees of freedom df1, df2
 1430  
         // numerator and denominator variances provided
 1431  
         public static double fTestProb(double var1, int df1, double var2, int df2){
 1432  0
             double fValue = var1/var2;
 1433  0
             double ddf1 = (double)df1;
 1434  0
             double ddf2 = (double)df2;
 1435  0
             double x = ddf2/(ddf2+ddf1*fValue);
 1436  0
             return Stat.incompleteBeta(df2/2.0D, df1/2.0D, x);
 1437  
         }
 1438  
 
 1439  
         // Returns the F-test value corresponding to a F-distribution probabilty, fProb,
 1440  
         //   for degrees of freedom df1, df2
 1441  
         public static double fTestValueGivenFprob(double fProb, int df1, int df2){
 1442  
 
 1443  
             // Create an array F-test value array
 1444  0
             int fTestsNum = 100;    // length of array
 1445  0
             double[] fTestValues = new double[fTestsNum];
 1446  0
             fTestValues[0]=0.0001D;             // lowest array value
 1447  0
             fTestValues[fTestsNum-1]=10000.0D;  // highest array value
 1448  
             // calculate array increment - log scale
 1449  0
             double diff = (Fmath.log10(fTestValues[fTestsNum-1])-Fmath.log10(fTestValues[0]))/(fTestsNum-1);
 1450  
             // Fill array
 1451  0
             for(int i=1; i<fTestsNum-1; i++){
 1452  0
                 fTestValues[i] = Math.pow(10.0D,(Fmath.log10(fTestValues[i-1])+diff));
 1453  
             }
 1454  
 
 1455  
             // calculate F test probability array corresponding to F-test value array
 1456  0
             double[] fTestProb = new double[fTestsNum];
 1457  0
             for(int i=0; i<fTestsNum; i++){
 1458  0
                 fTestProb[i] = Stat.fTestProb(fTestValues[i], df1, df2);
 1459  
             }
 1460  
 
 1461  
             // calculate F-test value for provided probability
 1462  
             // using bisection procedure
 1463  0
             double fTest0 = 0.0D;
 1464  0
             double fTest1 = 0.0D;
 1465  0
             double fTest2 = 0.0D;
 1466  
 
 1467  
             // find bracket for the F-test probabilities and calculate F-Test value from above arrays
 1468  0
             boolean test0 = true;
 1469  0
             boolean test1 = true;
 1470  0
             int i=0;
 1471  0
             int endTest=0;
 1472  0
             while(test0){
 1473  0
                 if(fProb==fTestProb[i]){
 1474  0
                     fTest0=fTestValues[i];
 1475  0
                     test0=false;
 1476  0
                     test1=false;
 1477  
                 }
 1478  
                 else{
 1479  0
                     if(fProb>fTestProb[i]){
 1480  0
                         test0=false;
 1481  0
                         if(i>0){
 1482  0
                             fTest1=fTestValues[i-1];
 1483  0
                             fTest2=fTestValues[i];
 1484  0
                             endTest=-1;
 1485  
                         }
 1486  
                         else{
 1487  0
                             fTest1=fTestValues[i]/10.0D;
 1488  0
                             fTest2=fTestValues[i];
 1489  
                         }
 1490  
                     }
 1491  
                     else{
 1492  0
                         i++;
 1493  0
                         if(i>fTestsNum-1){
 1494  0
                             test0=false;
 1495  0
                             fTest1=fTestValues[i-1];
 1496  0
                             fTest2=10.0D*fTestValues[i-1];
 1497  0
                             endTest=1;
 1498  
                         }
 1499  
                     }
 1500  
                 }
 1501  
             }
 1502  
 
 1503  
             // call bisection method
 1504  0
             if(test1)fTest0=fTestBisect(fProb, fTest1, fTest2, df1, df2, endTest);
 1505  
 
 1506  0
             return fTest0;
 1507  
         }
 1508  
 
 1509  
         // Bisection procedure for calculating and F-test value corresponding
 1510  
         //   to a given F-test probability
 1511  
         private static double fTestBisect(double fProb, double fTestLow, double fTestHigh, int df1, int df2, int endTest){
 1512  
 
 1513  0
             double funcLow = fProb - Stat.fTestProb(fTestLow, df1, df2);
 1514  0
             double funcHigh = fProb - Stat.fTestProb(fTestHigh, df1, df2);
 1515  0
             double fTestMid = 0.0D;
 1516  0
             double funcMid = 0.0;
 1517  0
             int nExtensions = 0;
 1518  0
             int nIter = 1000;           // iterations allowed
 1519  0
             double check = fProb*1e-6;  // tolerance for bisection
 1520  0
             boolean test0 = true;       // test for extending bracket
 1521  0
             boolean test1 = true;       // test for bisection procedure
 1522  0
             while(test0){
 1523  0
                 if(funcLow*funcHigh>0.0D){
 1524  0
                     if(endTest<0){
 1525  0
                         nExtensions++;
 1526  0
                         if(nExtensions>100){
 1527  0
                             System.out.println("Class: Stats\nMethod: fTestBisect\nProbability higher than range covered\nF-test value is less than "+fTestLow);
 1528  0
                             System.out.println("This value was returned");
 1529  0
                             fTestMid=fTestLow;
 1530  0
                             test0=false;
 1531  0
                             test1=false;
 1532  
                         }
 1533  0
                         fTestLow /= 10.0D;
 1534  0
                         funcLow = fProb - Stat.fTestProb(fTestLow, df1, df2);
 1535  
                     }
 1536  
                     else{
 1537  0
                         nExtensions++;
 1538  0
                         if(nExtensions>100){
 1539  0
                             System.out.println("Class: Stats\nMethod: fTestBisect\nProbability lower than range covered\nF-test value is greater than "+fTestHigh);
 1540  0
                             System.out.println("This value was returned");
 1541  0
                             fTestMid=fTestHigh;
 1542  0
                             test0=false;
 1543  0
                             test1=false;
 1544  
                         }
 1545  0
                         fTestHigh *= 10.0D;
 1546  0
                         funcHigh = fProb - Stat.fTestProb(fTestHigh, df1, df2);
 1547  
                     }
 1548  
                 }
 1549  
                 else{
 1550  0
                     test0=false;
 1551  
                 }
 1552  
 
 1553  0
                 int i=0;
 1554  0
                 while(test1){
 1555  0
                     fTestMid = (fTestLow+fTestHigh)/2.0D;
 1556  0
                     funcMid = fProb - Stat.fTestProb(fTestMid, df1, df2);
 1557  0
                     if(Math.abs(funcMid)<check){
 1558  0
                         test1=false;
 1559  
                     }
 1560  
                     else{
 1561  0
                         i++;
 1562  0
                         if(i>nIter){
 1563  0
                             System.out.println("Class: Stats\nMethod: fTestBisect\nmaximum number of iterations exceeded\ncurrent value of F-test value returned");
 1564  0
                             test1=false;
 1565  
                         }
 1566  0
                         if(funcMid*funcHigh>0){
 1567  0
                             funcHigh=funcMid;
 1568  0
                             fTestHigh=fTestMid;
 1569  
                         }
 1570  
                         else{
 1571  0
                             funcLow=funcMid;
 1572  0
                             fTestLow=fTestMid;
 1573  
                         }
 1574  
                     }
 1575  
                 }
 1576  0
             }
 1577  0
             return fTestMid;
 1578  
         }
 1579  
 
 1580  
         // Returns the Student t probability density function
 1581  
         public static double studentT(double tValue, int df){
 1582  0
             double ddf = (double)df;
 1583  0
             double dfterm = (ddf + 1.0D)/2.0D;
 1584  0
             return ((Stat.gamma(dfterm)/Stat.gamma(ddf/2))/Math.sqrt(ddf*Math.PI))*Math.pow(1.0D + tValue*tValue/ddf, -dfterm);
 1585  
         }
 1586  
 
 1587  
         // Returns the Student t cumulative distribution function probability
 1588  
         public static double studentTProb(double tValue, int df){
 1589  0
             double ddf = (double)df;
 1590  0
             double x = ddf/(ddf+tValue*tValue);
 1591  0
             return 0.5D*(1.0D + (Stat.incompleteBeta(ddf/2.0D, 0.5D, 1) - Stat.incompleteBeta(ddf/2.0D, 0.5D, x))*Fmath.sign(tValue));
 1592  
         }
 1593  
 
 1594  
         // Returns the A(t|n) distribution probabilty
 1595  
         public static double probAtn(double tValue, int df){
 1596  0
             double ddf = (double)df;
 1597  0
             double x = ddf/(ddf+tValue*tValue);
 1598  0
             return 1.0D - Stat.incompleteBeta(ddf/2.0D, 0.5D, x);
 1599  
         }
 1600  
 
 1601  
         // Distribute data into bins to obtain histogram
 1602  
         // zero bin position and upper limit provided
 1603  
         public static double[][] histogramBins(double[] data, double binWidth, double binZero, double binUpper){
 1604  0
             int n = 0;              // new array length
 1605  0
             int m = data.length;    // old array length;
 1606  0
             for(int i=0; i<m; i++)if(data[i]<=binUpper)n++;
 1607  0
             if(n!=m){
 1608  0
                 double[] newData = new double[n];
 1609  0
                 int j = 0;
 1610  0
                 for(int i=0; i<m; i++){
 1611  0
                     if(data[i]<=binUpper){
 1612  0
                         newData[j] = data[i];
 1613  0
                         j++;
 1614  
                     }
 1615  
                 }
 1616  0
                 System.out.println((m-n)+" data points, above histogram upper limit, excluded in Stat.histogramBins");
 1617  0
                 return histogramBins(newData, binWidth, binZero);
 1618  
             }
 1619  
             else{
 1620  0
                  return histogramBins(data, binWidth, binZero);
 1621  
 
 1622  
             }
 1623  
         }
 1624  
 
 1625  
         // Distribute data into bins to obtain histogram
 1626  
         // zero bin position provided
 1627  
         public static double[][] histogramBins(double[] data, double binWidth, double binZero){
 1628  0
             double dmax = Fmath.maximum(data);
 1629  0
             int nBins = (int) Math.ceil((dmax - binZero)/binWidth);
 1630  0
             if(binZero+nBins*binWidth>dmax)nBins++;
 1631  0
             int nPoints = data.length;
 1632  0
             int[] dataCheck = new int[nPoints];
 1633  0
             for(int i=0; i<nPoints; i++)dataCheck[i]=0;
 1634  0
             double[]binWall = new double[nBins+1];
 1635  0
             binWall[0]=binZero;
 1636  0
             for(int i=1; i<=nBins; i++){
 1637  0
                 binWall[i] = binWall[i-1] + binWidth;
 1638  
             }
 1639  0
             double[][] binFreq = new double[2][nBins];
 1640  0
             for(int i=0; i<nBins; i++){
 1641  0
                 binFreq[0][i]= (binWall[i]+binWall[i+1])/2.0D;
 1642  0
                 binFreq[1][i]= 0.0D;
 1643  
             }
 1644  0
             boolean test = true;
 1645  
 
 1646  0
             for(int i=0; i<nPoints; i++){
 1647  0
                 test=true;
 1648  0
                 int j=0;
 1649  0
                 while(test){
 1650  0
                     if(j==nBins-1){
 1651  0
                         if(data[i]>=binWall[j] && data[i]<=binWall[j+1]*(1.0D + Stat.histTol)){
 1652  0
                             binFreq[1][j]+= 1.0D;
 1653  0
                             dataCheck[i]=1;
 1654  0
                             test=false;
 1655  
                         }
 1656  
                     }
 1657  
                     else{
 1658  0
                         if(data[i]>=binWall[j] && data[i]<binWall[j+1]){
 1659  0
                             binFreq[1][j]+= 1.0D;
 1660  0
                             dataCheck[i]=1;
 1661  0
                             test=false;
 1662  
                         }
 1663  
                     }
 1664  0
                     if(test){
 1665  0
                         if(j==nBins-1){
 1666  0
                             test=false;
 1667  
                         }
 1668  
                         else{
 1669  0
                             j++;
 1670  
                         }
 1671  
                     }
 1672  
                 }
 1673  
             }
 1674  0
             int nMissed=0;
 1675  0
             for(int i=0; i<nPoints; i++)if(dataCheck[i]==0){
 1676  0
                 nMissed++;
 1677  0
                 System.out.println("p " + i + " " + data[i] + " " + binWall[0] + " " + binWall[nBins]);
 1678  
             }
 1679  0
             if(nMissed>0)System.out.println(nMissed+" data points, outside histogram limits, excluded in Stat.histogramBins");
 1680  0
             return binFreq;
 1681  
         }
 1682  
 
 1683  
         // Distribute data into bins to obtain histogram
 1684  
         // zero bin position calculated
 1685  
         public static double[][] histogramBins(double[] data, double binWidth){
 1686  
 
 1687  0
             double dmin = Fmath.minimum(data);
 1688  0
             double dmax = Fmath.maximum(data);
 1689  0
             double span = dmax - dmin;
 1690  0
             double binZero = dmin;
 1691  0
             int nBins = (int) Math.ceil(span/binWidth);
 1692  0
             double histoSpan = ((double)nBins)*binWidth;
 1693  0
             double rem = histoSpan - span;
 1694  0
             if(rem>=0){
 1695  0
                 binZero -= rem/2.0D;
 1696  
             }
 1697  
             else{
 1698  0
                 if(Math.abs(rem)/span>histTol){
 1699  
                     // readjust binWidth
 1700  0
                     boolean testBw = true;
 1701  0
                     double incr = histTol/nBins;
 1702  0
                     int iTest = 0;
 1703  0
                     while(testBw){
 1704  0
                        binWidth += incr;
 1705  0
                        histoSpan = ((double)nBins)*binWidth;
 1706  0
                         rem = histoSpan - span;
 1707  0
                         if(rem<0){
 1708  0
                             iTest++;
 1709  0
                             if(iTest>1000){
 1710  0
                                 testBw = false;
 1711  0
                                 System.out.println("histogram method could not encompass all data within histogram\nContact Michael thomas Flanagan");
 1712  
                             }
 1713  
                         }
 1714  
                         else{
 1715  0
                             testBw = false;
 1716  
                         }
 1717  
                     }
 1718  
                 }
 1719  
             }
 1720  
 
 1721  0
             return Stat.histogramBins(data, binWidth, binZero);
 1722  
         }
 1723  
 
 1724  
         // factorial of n
 1725  
         // argument and return are integer, therefore limited to 0<=n<=12
 1726  
         // see below for long and double arguments
 1727  
         public static int factorial(int n){
 1728  0
                 if(n<0)throw new IllegalArgumentException("n must be a positive integer");
 1729  0
                 if(n>12)throw new IllegalArgumentException("n must less than 13 to avoid integer overflow\nTry long or double argument");
 1730  0
                 int f = 1;
 1731  0
                 for(int i=1; i<=n; i++)f*=i;
 1732  0
                 return f;
 1733  
         }
 1734  
 
 1735  
         // factorial of n
 1736  
         // argument and return are long, therefore limited to 0<=n<=20
 1737  
         // see below for double argument
 1738  
         public static long factorial(long n){
 1739  0
                 if(n<0)throw new IllegalArgumentException("n must be a positive integer");
 1740  0
                 if(n>20)throw new IllegalArgumentException("n must less than 21 to avoid long integer overflow\nTry double argument");
 1741  0
                 long f = 1;
 1742  0
                 for(int i=1; i<=n; i++)f*=i;
 1743  0
                 return f;
 1744  
         }
 1745  
 
 1746  
         // factorial of n
 1747  
         // Argument is of type double but must be, numerically, an integer
 1748  
         // factorial returned as double but is, numerically, should be an integer
 1749  
         // numerical rounding may makes this an approximation after n = 21
 1750  
         public static double factorial(double n){
 1751  0
                 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?");
 1752  0
                 double f = 1.0D;
 1753  0
                 int nn = (int)n;
 1754  0
                 for(int i=1; i<=nn; i++)f*=i;
 1755  0
                 return f;
 1756  
         }
 1757  
 
 1758  
         // log to base e of the factorial of n
 1759  
         // log[e](factorial) returned as double
 1760  
         // numerical rounding may makes this an approximation
 1761  
         public static double logFactorial(int n){
 1762  0
                 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?");
 1763  0
                 double f = 0.0D;
 1764  0
                 for(int i=2; i<=n; i++)f+=Math.log(i);
 1765  0
                 return f;
 1766  
         }
 1767  
 
 1768  
         // log to base e of the factorial of n
 1769  
         // Argument is of type double but must be, numerically, an integer
 1770  
         // log[e](factorial) returned as double
 1771  
         // numerical rounding may makes this an approximation
 1772  
         public static double logFactorial(double n){
 1773  0
         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?");
 1774  0
                 double f = 0.0D;
 1775  0
                 int nn = (int)n;
 1776  0
                 for(int i=2; i<=nn; i++)f+=Math.log(i);
 1777  0
                 return f;
 1778  
         }
 1779  
 
 1780  
         // Calculate correlation coefficient
 1781  
         // x y data as double
 1782  
         public static double corrCoeff(double[] xx, double[]yy){
 1783  
 
 1784  0
             double temp0 = 0.0D, temp1 = 0.0D;  // working variables
 1785  0
             int nData = xx.length;
 1786  0
             if(yy.length!=nData)throw new IllegalArgumentException("array lengths must be equal");
 1787  0
             int df = nData-1;
 1788  
             // means
 1789  0
             double mx = 0.0D;
 1790  0
             double my = 0.0D;
 1791  0
             for(int i=0; i<nData; i++){
 1792  0
                 mx += xx[i];
 1793  0
                 my += yy[i];
 1794  
             }
 1795  0
             mx /= nData;
 1796  0
             my /= nData;
 1797  
 
 1798  
             // calculate sample variances
 1799  0
             double s2xx = 0.0D;
 1800  0
             double s2yy = 0.0D;
 1801  0
             double s2xy = 0.0D;
 1802  0
             for(int i=0; i<nData; i++){
 1803  0
                 s2xx += Fmath.square(xx[i]-mx);
 1804  0
                 s2yy += Fmath.square(yy[i]-my);
 1805  0
                 s2xy += (xx[i]-mx)*(yy[i]-my);
 1806  
             }
 1807  0
             s2xx /= df;
 1808  0
             s2yy /= df;
 1809  0
             s2xy /= df;
 1810  
 
 1811  
             // calculate corelation coefficient
 1812  0
             double sampleR = s2xy/Math.sqrt(s2xx*s2yy);
 1813  
 
 1814  0
             return sampleR;
 1815  
         }
 1816  
 
 1817  
         // Calculate correlation coefficient
 1818  
         // x y data as float
 1819  
         public static float corrCoeff(float[] x, float[] y){
 1820  0
             int nData = x.length;
 1821  0
             if(y.length!=nData)throw new IllegalArgumentException("array lengths must be equal");
 1822  0
             int n = x.length;
 1823  0
             double[] xx = new double[n];
 1824  0
             double[] yy = new double[n];
 1825  0
             for(int i=0; i<n; i++){
 1826  0
                 xx[i] = (double)x[i];
 1827  0
                 yy[i] = (double)y[i];
 1828  
             }
 1829  0
             return (float)Stat.corrCoeff(xx, yy);
 1830  
         }
 1831  
 
 1832  
         // Calculate correlation coefficient
 1833  
         // x y data as int
 1834  
         public static double corrCoeff(int[] x, int[]y){
 1835  0
             int n = x.length;
 1836  0
             if(y.length!=n)throw new IllegalArgumentException("array lengths must be equal");
 1837  
 
 1838  0
             double[] xx = new double[n];
 1839  0
             double[] yy = new double[n];
 1840  0
             for(int i=0; i<n; i++){
 1841  0
                 xx[i] = (double)x[i];
 1842  0
                 yy[i] = (double)y[i];
 1843  
             }
 1844  0
             return Stat.corrCoeff(xx, yy);
 1845  
         }
 1846  
 
 1847  
         // Calculate weighted correlation coefficient
 1848  
         // x y data and weights w as double
 1849  
         public static double corrCoeff(double[] x, double[]y, double[] w){
 1850  0
             int n = x.length;
 1851  0
             if(y.length!=n)throw new IllegalArgumentException("x and y array lengths must be equal");
 1852  0
             if(w.length!=n)throw new IllegalArgumentException("x and weight array lengths must be equal");
 1853  
 
 1854  0
             double sxy = Stat.covariance(x, y, w);
 1855  0
             double sx = Stat.variance(x, w);
 1856  0
             double sy = Stat.variance(y, w);
 1857  0
             return sxy/Math.sqrt(sx*sy);
 1858  
         }
 1859  
 
 1860  
         // Calculate correlation coefficient
 1861  
         // Binary data x and y
 1862  
         // Input is the frequency matrix, F, elements, f(i,j)
 1863  
         // f(0,0) - element00 - frequency of x and y both = 1
 1864  
         // f(0,1) - element01 - frequency of x = 0 and y = 1
 1865  
         // f(1,0) - element10 - frequency of x = 1 and y = 0
 1866  
         // f(1,1) - element11 - frequency of x and y both = 0
 1867  
         public static double corrCoeff(int element00, int element01, int element10, int element11){
 1868  0
             return ((double)(element00*element11 - element01*element10))/Math.sqrt((double)((element00+element01)*(element10+element11)*(element00+element10)*(element01+element11)));
 1869  
         }
 1870  
 
 1871  
         // Calculate correlation coefficient
 1872  
         // Binary data x and y
 1873  
         // Input is the frequency matrix, F
 1874  
         // F(0,0) - frequency of x and y both = 1
 1875  
         // F(0,1) - frequency of x = 0 and y = 1
 1876  
         // F(1,0) - frequency of x = 1 and y = 0
 1877  
         // F(1,1) - frequency of x and y both = 0
 1878  
         public static double corrCoeff(int[][] freqMatrix){
 1879  0
             double element00 = (double)freqMatrix[0][0];
 1880  0
             double element01 = (double)freqMatrix[0][1];
 1881  0
             double element10 = (double)freqMatrix[1][0];
 1882  0
             double element11 = (double)freqMatrix[1][1];
 1883  0
             return ((element00*element11 - element01*element10))/Math.sqrt(((element00+element01)*(element10+element11)*(element00+element10)*(element01+element11)));
 1884  
         }
 1885  
 
 1886  
         // Linear correlation coefficient single probablity
 1887  
         // old name calls renamed method
 1888  
         public static double linearCorrCoeff(double rCoeff, int nu){
 1889  0
             return Stat.corrCoeffPdf(rCoeff, nu);
 1890  
         }
 1891  
 
 1892  
         // Linear correlation coefficient single probablity
 1893  
         public static double corrCoeffPdf(double rCoeff, int nu){
 1894  0
             if(Math.abs(rCoeff)>1.0D)throw new IllegalArgumentException("|Correlation coefficient| > 1 :  " + rCoeff);
 1895  
 
 1896  0
             double a = ((double)nu - 2.0D)/2.0D;
 1897  0
             double y = Math.pow((1.0D - Fmath.square(rCoeff)),a);
 1898  
 
 1899  0
             double preterm = Math.exp(Stat.logGamma((nu+1.0D)/2.0)-Stat.logGamma(nu/2.0D))/Math.sqrt(Math.PI);
 1900  
 
 1901  0
             return preterm*y;
 1902  
         }
 1903  
 
 1904  
         // Weibull cumulative distribution function
 1905  
         // probability that a variate will assume  a value less than the upperlimit
 1906  
         public static double weibullProb(double mu, double sigma, double gamma, double upperlimit){
 1907  0
                 double arg = (upperlimit - mu)/sigma;
 1908  0
                 double y = 0.0D;
 1909  0
                 if(arg>0.0D)y = 1.0D - Math.exp(-Math.pow(arg, gamma));
 1910  0
                 return y;
 1911  
         }
 1912  
 
 1913  
         // Weibull cumulative distribution function
 1914  
         // probability that a variate will assume a value between the lower and  the upper limits
 1915  
         public static double weibullProb(double mu, double sigma, double gamma, double lowerlimit, double upperlimit){
 1916  0
                 double arg1 = (lowerlimit - mu)/sigma;
 1917  0
                 double arg2 = (upperlimit - mu)/sigma;
 1918  0
                 double term1 = 0.0D, term2 = 0.0D;
 1919  0
                 if(arg1>=0.0D)term1 = -Math.exp(-Math.pow(arg1, gamma));
 1920  0
                 if(arg2>=0.0D)term2 = -Math.exp(-Math.pow(arg2, gamma));
 1921  0
                 return term2-term1;
 1922  
         }
 1923  
 
 1924  
         // Weibull probability
 1925  
         public static double weibull(double mu,double sigma, double gamma, double x){
 1926  0
                 double arg =(x-mu)/sigma;
 1927  0
                 double y = 0.0D;
 1928  0
                 if(arg>=0.0D){
 1929  0
                     y = (gamma/sigma)*Math.pow(arg, gamma-1.0D)*Math.exp(-Math.pow(arg, gamma));
 1930  
                 }
 1931  0
                 return y;
 1932  
         }
 1933  
 
 1934  
         // Weibull mean
 1935  
         public static double weibullMean(double mu,double sigma, double gamma){
 1936  0
                 return mu + sigma*Stat.gamma(1.0D/gamma+1.0D);
 1937  
         }
 1938  
 
 1939  
         // Weibull standard deviation
 1940  
         public static double weibullStandDev(double sigma, double gamma){
 1941  0
                 double y = Stat.gamma(2.0D/gamma+1.0D)-Fmath.square(Stat.gamma(1.0D/gamma+1.0D));
 1942  0
                 return sigma*Math.sqrt(y);
 1943  
         }
 1944  
 
 1945  
         // Weibull mode
 1946  
         public static double weibullMode(double mu,double sigma, double gamma){
 1947  0
             double y=mu;
 1948  0
             if(gamma>1.0D){
 1949  0
                 y = mu + sigma*Math.pow((gamma-1.0D)/gamma, 1.0D/gamma);
 1950  
             }
 1951  0
             return y;
 1952  
         }
 1953  
 
 1954  
         // Weibull median
 1955  
         public static double weibullMedian(double mu,double sigma, double gamma){
 1956  0
             return mu + sigma*Math.pow(Math.log(2.0D),1.0D/gamma);
 1957  
         }
 1958  
 
 1959  
         // Returns an array of Weibull (Type III EVD) random deviates - clock seed
 1960  
         // mu  =  location parameter, sigma = cale parameter, gamma = shape parametern = length of array
 1961  
         public static double[] weibullRand(double mu, double sigma, double gamma, int n){
 1962  0
                 double[] ran = new double[n];
 1963  0
                 Random rr = new Random();
 1964  0
                 for(int i=0; i<n; i++){
 1965  0
                      ran[i] = Math.pow(-Math.log(1.0D-rr.nextDouble()),1.0D/gamma)*sigma + mu;
 1966  
                 }
 1967  0
                 return ran;
 1968  
         }
 1969  
 
 1970  
         // Returns an array of Weibull (Type III EVD) random deviates - user supplied seed
 1971  
         // mu  =  location parameter, sigma = cale parameter, gamma = shape parametern = length of array
 1972  
         public static double[] weibullRand(double mu, double sigma, double gamma, int n, long seed){
 1973  0
                 double[] ran = new double[n];
 1974  0
                 Random rr = new Random(seed);
 1975  0
                 for(int i=0; i<n; i++){
 1976  0
                      ran[i] = Math.pow(-Math.log(1.0D-rr.nextDouble()),1.0D/gamma)*sigma + mu;
 1977  
                 }
 1978  0
                 return ran;
 1979  
         }
 1980  
 
 1981  
         // Frechet cumulative distribution function
 1982  
         // probability that a variate will assume  a value less than the upperlimit
 1983  
         public static double frechetProb(double mu, double sigma, double gamma, double upperlimit){
 1984  0
                 double arg = (upperlimit - mu)/sigma;
 1985  0
                 double y = 0.0D;
 1986  0
                 if(arg>0.0D)y = Math.exp(-Math.pow(arg, -gamma));
 1987  0
                 return y;
 1988  
         }
 1989  
 
 1990  
 
 1991  
         // Frechet cumulative distribution function
 1992  
         // probability that a variate will assume a value between the lower and  the upper limits
 1993  
         public static double frechetProb(double mu, double sigma, double gamma, double lowerlimit, double upperlimit){
 1994  0
                 double arg1 = (lowerlimit - mu)/sigma;
 1995  0
                 double arg2 = (upperlimit - mu)/sigma;
 1996  0
                 double term1 = 0.0D, term2 = 0.0D;
 1997  0
                 if(arg1>=0.0D)term1 = Math.exp(-Math.pow(arg1, -gamma));
 1998  0
                 if(arg2>=0.0D)term2 = Math.exp(-Math.pow(arg2, -gamma));
 1999  0
                 return term2-term1;
 2000  
         }
 2001  
 
 2002  
         // Exponential cumulative distribution function
 2003  
         // probability that a variate will assume  a value less than the upperlimit
 2004  
         public static double exponentialProb(double mu, double sigma, double upperlimit){
 2005  0
                 double arg = (upperlimit - mu)/sigma;
 2006  0
                 double y = 0.0D;
 2007  0
                 if(arg>0.0D)y = 1.0D - Math.exp(-arg);
 2008  0
                 return y;
 2009  
         }
 2010  
 
 2011  
         // Exponential cumulative distribution function
 2012  
         // probability that a variate will assume a value between the lower and  the upper limits
 2013  
         public static double exponentialProb(double mu, double sigma, double lowerlimit, double upperlimit){
 2014  0
                 double arg1 = (lowerlimit - mu)/sigma;
 2015  0
                 double arg2 = (upperlimit - mu)/sigma;
 2016  0
                 double term1 = 0.0D, term2 = 0.0D;
 2017  0
                 if(arg1>=0.0D)term1 = -Math.exp(-arg1);
 2018  0
                 if(arg2>=0.0D)term2 = -Math.exp(-arg2);
 2019  0
                 return term2-term1;
 2020  
         }
 2021  
 
 2022  
         // Exponential probability
 2023  
         public static double exponential(double mu,double sigma, double x){
 2024  0
                 double arg =(x-mu)/sigma;
 2025  0
                 double y = 0.0D;
 2026  0
                 if(arg>=0.0D){
 2027  0
                     y = Math.exp(-arg)/sigma;
 2028  
                 }
 2029  0
                 return y;
 2030  
         }
 2031  
 
 2032  
         // Exponential mean
 2033  
         public static double exponentialMean(double mu, double sigma){
 2034  0
                 return mu + sigma;
 2035  
         }
 2036  
 
 2037  
         // Exponential standard deviation
 2038  
         public static double exponentialStandDev(double sigma){
 2039  0
                 return sigma;
 2040  
         }
 2041  
 
 2042  
         // Exponential mode
 2043  
         public static double exponentialMode(double mu){
 2044  0
             return mu;
 2045  
         }
 2046  
 
 2047  
         // Exponential median
 2048  
         public static double exponentialMedian(double mu,double sigma){
 2049  0
             return mu + sigma*Math.log(2.0D);
 2050  
         }
 2051  
 
 2052  
         // Returns an array of Exponential random deviates - clock seed
 2053  
         // mu  =  location parameter, sigma = cale parameter, gamma = shape parametern = length of array
 2054  
         public static double[] exponentialRand(double mu, double sigma, int n){
 2055  0
                 double[] ran = new double[n];
 2056  0
                 Random rr = new Random();
 2057  0
                 for(int i=0; i<n; i++){
 2058  0
                      ran[i] = mu - Math.log(1.0D-rr.nextDouble())*sigma;
 2059  
                 }
 2060  0
                 return ran;
 2061  
         }
 2062  
 
 2063  
         // Returns an array of Exponential random deviates - user supplied seed
 2064  
         // mu  =  location parameter, sigma = cale parameter, gamma = shape parametern = length of array
 2065  
         public static double[] exponentialRand(double mu, double sigma, int n, long seed){
 2066  0
                 double[] ran = new double[n];
 2067  0
                 Random rr = new Random(seed);
 2068  0
                 for(int i=0; i<n; i++){
 2069  0
                      ran[i] = mu - Math.log(1.0D-rr.nextDouble())*sigma;
 2070  
                 }
 2071  0
                 return ran;
 2072  
         }
 2073  
  }