/[projects]/dao/DelphiScanner/Components/tpsystools_4.04/source/StStat.pas
ViewVC logotype

Annotation of /dao/DelphiScanner/Components/tpsystools_4.04/source/StStat.pas

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (hide annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 10 months ago) by torben
File size: 69628 byte(s)
Added tpsystools component
1 torben 2671 // Upgraded to Delphi 2009: Sebastian Zierer
2    
3     (* ***** BEGIN LICENSE BLOCK *****
4     * Version: MPL 1.1
5     *
6     * The contents of this file are subject to the Mozilla Public License Version
7     * 1.1 (the "License"); you may not use this file except in compliance with
8     * the License. You may obtain a copy of the License at
9     * http://www.mozilla.org/MPL/
10     *
11     * Software distributed under the License is distributed on an "AS IS" basis,
12     * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13     * for the specific language governing rights and limitations under the
14     * License.
15     *
16     * The Original Code is TurboPower SysTools
17     *
18     * The Initial Developer of the Original Code is
19     * TurboPower Software
20     *
21     * Portions created by the Initial Developer are Copyright (C) 1996-2002
22     * the Initial Developer. All Rights Reserved.
23     *
24     * Contributor(s):
25     *
26     * ***** END LICENSE BLOCK ***** *)
27    
28     {*********************************************************}
29     {* SysTools: StStat.pas 4.04 *}
30     {*********************************************************}
31     {* SysTools: Statistical math functions modeled on *}
32     {* those in Excel *}
33     {*********************************************************}
34    
35     {$I StDefine.inc}
36    
37     unit StStat;
38    
39     { The statistical distribution functions return results in singles }
40     { since the fractional accuracy of these is typically about 3e-7. }
41    
42     interface
43    
44     uses
45     Windows,
46     {$IFDEF UseMathUnit}
47     Math,
48     {$ELSE}
49     StMath,
50     {$ENDIF}
51     SysUtils, StConst, StBase;
52    
53     {AVEDEV}
54     function AveDev(const Data: array of Double) : Double;
55     function AveDev16(const Data; NData : Integer) : Double;
56     {-Returns the average of the absolute deviations of data points from their
57     mean. AveDev is a measure of the variability in a data set.
58     }
59    
60     {CONFIDENCE}
61     function Confidence(Alpha, StandardDev : Double; Size : LongInt) : Double;
62     {-Returns the confidence interval for a population mean.
63     The confidence interval is a range on either side of a sample mean.
64     Alpha is the significance level used to compute the confidence level.
65     The confidence level equals 100*(1 - Alpha)%, or in other words,
66     an Alpha of 0.05 indicates a 95 percent confidence level.
67     StandardDev is the population standard deviation for the data range
68     and is assumed to be known.
69     Size is the sample Size.
70     }
71    
72     {CORREL}
73     function Correlation(const Data1, Data2 : array of Double) : Double;
74     function Correlation16(const Data1, Data2; NData : Integer) : Double;
75     {-Returns the correlation coefficient of the Data1 and Data2 arrays.
76     Use the correlation coefficient to determine the relationship between
77     two data sets.
78     This function also returns the same value as the PEARSON function
79     in Excel.
80     }
81    
82     {COVAR}
83     function Covariance(const Data1, Data2 : array of Double) : Double;
84     function Covariance16(const Data1, Data2; NData : Integer) : Double;
85     {-Returns covariance, the average of products of deviations, for the Data1
86     and Data2 arrays. Use covariance to determine the relationship between
87     two data sets.
88     }
89    
90     {DEVSQ}
91     function DevSq(const Data : array of Double) : Double;
92     function DevSq16(const Data; NData : Integer) : Double;
93     {-Returns the sum of squares of deviations of data points from their
94     sample mean.
95     }
96    
97     {FREQUENCY}
98     procedure Frequency(const Data : array of Double; const Bins : array of Double;
99     var Counts : array of LongInt);
100     procedure Frequency16(const Data; NData : Integer; const Bins; NBins : Integer;
101     var Counts);
102     {-Calculates how often values occur within an array of data,
103     and then returns an array of counts.
104     Data is an array of values for which you want to count frequencies.
105     Bins is an array of intervals into which you want to group the values in
106     Data.
107     Counts is an array into which the frequency counts are returned. Counts
108     must have one more element than does Bins. The first element of Counts
109     has all items less than the first number in Bins. The next element of
110     Counts is the items that fall between Bins[0] and Bins[1]. The last
111     element of Counts has all items greater than the last number in Bins.
112     }
113    
114     {GEOMEAN}
115     function GeometricMean(const Data : array of Double) : Double;
116     function GeometricMean16(const Data; NData : Integer) : Double;
117     {-Returns the geometric mean of an array of positive data. The geometric
118     mean is the n'th root of the product of n positive numbers.}
119    
120     {HARMEAN}
121     function HarmonicMean(const Data : array of Double) : Double;
122     function HarmonicMean16(const Data; NData : Integer) : Double;
123     {-Returns the harmonic mean of an array of data. The harmonic mean is the
124     reciprocal of the arithmetic mean of reciprocals.}
125    
126     {LARGE}
127     function Largest(const Data : array of Double; K : Integer) : Double;
128     function Largest16(const Data; NData : Integer; K : Integer) : Double;
129     {-Returns the K'th largest value in an array of data. You can use this
130     function to select a value based on its relative standing.}
131    
132     {MEDIAN}
133     function Median(const Data : array of Double) : Double;
134     function Median16(const Data; NData : Integer) : Double;
135     {-Returns the median of the given numbers. The median is the number in the
136     middle of a set of numbers; that is, half the numbers have values that
137     are greater than the median, and half have values that are less.
138     If there is an even number of numbers in the set, MEDIAN calculates
139     the average of the two numbers in the middle.
140     }
141    
142     {MODE}
143     function Mode(const Data: array of Double) : Double;
144     function Mode16(const Data; NData : Integer) : Double;
145     {-Returns the most frequently occurring, or repetitive, value in an array
146     of data. In case of duplicate frequencies it returns the smallest
147     such value.}
148    
149     {PERCENTILE}
150     function Percentile(const Data : array of Double; K : Double) : Double;
151     function Percentile16(const Data; NData : Integer; K : Double) : Double;
152     {-Returns the value of the K'th percentile of an array of data.
153     K is the percentile value, a number between 0 and 1. If K is not a
154     multiple of 1/(n-1) where n is the size of Data, Percentile
155     interpolates between the closest bins.
156     }
157    
158     {PERCENTRANK}
159     function PercentRank(const Data : array of Double; X : Double) : Double;
160     function PercentRank16(const Data; NData : Integer; X : Double) : Double;
161     {-Returns the percentile position of a value within an array of data.
162     X is a data value. If X is not found within the array, PercentRank
163     interpolates between the closest data points.
164     }
165    
166     {PERMUT}
167     function Permutations(Number, NumberChosen : Integer) : Extended;
168     {-Returns the number of permutations for a given Number of objects that
169     can be selected from Number objects. A permutation is any set or subset
170     of objects or events where internal order is significant.
171     Permutations are different from combinations, for which the internal order
172     is not significant.
173     Number is an Integer that describes the number of objects.
174     NumberChosen is an Integer that describes the number of objects in
175     each permutation.
176     }
177    
178     {COMBIN}
179     function Combinations(Number, NumberChosen : Integer) : Extended;
180     {-Returns the number of combinations for a given Number of objects that
181     can be selected from Number objects. A combination is any set or subset
182     of objects or events where internal order is not significant.
183     Number is an Integer that describes the number of objects.
184     NumberChosen is an Integer that describes the number of objects in
185     each permutation.
186     }
187    
188     {FACT}
189     function Factorial(N : Integer) : Extended;
190     {-Returns N! as a floating point number.
191     Extended is used for range, not accuracy.
192     }
193    
194     {RANK}
195     function Rank(Number : Double; const Data : array of Double;
196     Ascending : Boolean) : Integer;
197     function Rank16(Number : Double; const Data; NData : Integer;
198     Ascending : Boolean) : Integer;
199     {-Returns the rank of a number in a list of numbers. If you were to sort
200     a list that contained no duplicates, the rank of the Number would be its
201     position within the sorted list.
202     Number is the number whose rank you want.
203     Data is the list of numbers.
204     If Ascending is True the rank is measured from the beginning of the
205     array; otherwise from the end of the array.
206     If the Number is not found in the array, 0 is returned. Numbers that
207     appear multiple times all have the same rank, but they affect the
208     rank of numbers appearing after them. For example, in a list of
209     Integers, if the number 10 appears twice and has a rank of 5,
210     then 11 would have a rank of 7 (no number would have a rank of 6).
211     Be sure to sort Data before calling this routine if you want an
212     unambiguous ranking.
213     }
214    
215     {SMALL}
216     function Smallest(const Data : array of Double; K : Integer) : Double;
217     function Smallest16(const Data; NData : Integer; K : Integer) : Double;
218     {-Returns the K'th smallest value in an array of data. You can use this
219     function to select a value based on its relative standing.}
220    
221     {TRIMMEAN}
222     function TrimMean(const Data : array of Double; Percent : Double) : Double;
223     function TrimMean16(const Data; NData : Integer; Percent : Double) : Double;
224     {-Returns the mean of Data after trimming Percent points from the data set.
225     If Percent is 0.2 and there are 20 points in Data, the 2 largest and 2
226     smallest points would be dropped before computing the mean. Percent must
227     be a number between 0 and 1.
228     }
229    
230     {--------------------------------------------------------------------------}
231    
232     type
233     {full statistics for a linear regression}
234     TStLinEst = record
235     B0, B1 : Double; {model coefficients}
236     seB0, seB1 : Double; {standard error of model coefficients}
237     R2 : Double; {coefficient of determination}
238     sigma : Double; {standard error of regression}
239     SSr, SSe : Double; {elements for ANOVA table}
240     F0 : Double; {F-statistic to test B1=0}
241     df : Integer; {denominator degrees of freedom for F-statistic}
242     end;
243    
244     {LINEST}
245     procedure LinEst(const KnownY : array of Double;
246     const KnownX : array of Double; var LF : TStLinEst; ErrorStats : Boolean);
247     procedure LinEst16(const KnownY; const KnownX; NData : Integer;
248     var LF : TStLinEst; ErrorStats : Boolean);
249     {-Performs linear fit to data and returns coefficients and error
250     statistics.
251     KnownY is the dependent array of known data points.
252     KnownX is the independent array of known data points.
253     NData must be greater than 2.
254     If ErrorStats is FALSE, only B0 and B1 are computed; the other fields
255     of TStLinEst are set to 0.0.
256     See declaration of TStLinEst for returned data.
257    
258     }
259    
260     {LOGEST}
261     procedure LogEst(const KnownY : array of Double;
262     const KnownX : array of Double; var LF : TStLinEst; ErrorStats : Boolean);
263     procedure LogEst16(const KnownY; const KnownX; NData : Integer;
264     var LF : TStLinEst; ErrorStats : Boolean);
265     {-Performs log-linear fit to data and returns coefficients and error
266     statistics.
267     KnownY is the dependent array of known data points.
268     KnownX is the independent array of known data points.
269     NData must be greater than 2.
270     KnownY is transformed using ln(KnownY) before fitting:
271     y = B0*B1^x implies that ln(y) = ln(B0)+X*ln(B1)
272     In the returned LF, B0 and B1 are returned as shown. Other values in LF
273     are in terms of the log transformation.
274     If ErrorStats is FALSE, only B0 and B1 are computed; the other fields
275     of TStLinEst are set to 0.0.
276     See declaration of TStLinEst for returned data.
277     }
278    
279     {FORECAST}
280     function Forecast(X : Double; const KnownY: array of Double;
281     const KnownX : array of Double) : Double;
282     function Forecast16(X : Double; const KnownY; const KnownX;
283     NData : Integer) : Double;
284     {-Calculates a future value by using existing values. The predicted value
285     is a y-value for a given X-value. The known values are existing X-values
286     and y-values, and the new value is predicted by using linear regression.
287     X is the data point for which you want to predict a value.
288     KnownY is the dependent array of known data points.
289     KnownX is the independent array of known data points.
290     }
291    
292     {similar to GROWTH but more consistent with FORECAST}
293     function ForecastExponential(X : Double; const KnownY : array of Double;
294     const KnownX : array of Double) : Double;
295     function ForecastExponential16(X : Double; const KnownY; const KnownX;
296     NData : Integer) : Double;
297     {-Calculates a future value by using existing values. The predicted value
298     is a y-value for a given X-value. The known values are existing X-values
299     and y-values, and the new value is predicted by using linear regression
300     to an exponential growth model, y = B0*B1^X.
301     X is the data point for which you want to predict a value.
302     KnownY is the dependent array of known data points.
303     KnownX is the independent array of known data points.
304     }
305    
306     {INTERCEPT}
307     function Intercept(const KnownY : array of Double;
308     const KnownX : array of Double) : Double;
309     function Intercept16(const KnownY; const KnownX; NData : Integer) : Double;
310     {-Calculates the point at which a line will intersect the y-axis by using
311     existing X-values and y-values. The intercept point is based on a best-fit
312     regression line plotted through the known X-values and known y-values.
313     Use the intercept when you want to determine the value of the dependent
314     variable when the independent variable is 0 (zero).
315     }
316    
317     {RSQ}
318     function RSquared(const KnownY : array of Double;
319     const KnownX : array of Double) : Double;
320     function RSquared16(const KnownY; const KnownX; NData : Integer) : Double;
321     {-Returns the square of the Pearson product moment correlation coefficient
322     through data points in KnownY's and KnownX's. The r-squared value can
323     be interpreted as the proportion of the variance in y attributable to
324     the variance in X.
325     }
326    
327     {SLOPE}
328     function Slope(const KnownY : array of Double;
329     const KnownX : array of Double) : Double;
330     function Slope16(const KnownY; const KnownX; NData : Integer) : Double;
331     {-Returns the slope of the linear regression line through data points in
332     KnownY's and KnownX's. The slope is the vertical distance divided by the
333     horizontal distance between any two points on the line, which is the rate
334     of change along the regression line.
335     }
336    
337     {STEYX}
338     function StandardErrorY(const KnownY : array of Double;
339     const KnownX : array of Double) : Double;
340     function StandardErrorY16(const KnownY; const KnownX;
341     NData : Integer) : Double;
342     {-Returns the standard error of the predicted y-value for each X in a linear
343     regression. The standard error is a measure of the amount of error in the
344     prediction of y for an individual X.
345     }
346    
347     {--------------------------------------------------------------------------}
348    
349     {BETADIST}
350     function BetaDist(X, Alpha, Beta, A, B : Single) : Single;
351     {-Returns the cumulative beta probability density function.
352     The cumulative beta probability density function is commonly used to
353     study variation in the percentage of something across samples.
354     X is the value at which to evaluate the function, A <= X <= B.
355     Alpha is a parameter to the distribution.
356     Beta is a parameter to the distribution.
357     A is the lower bound to the interval of X.
358     B is the upper bound to the interval of X.
359     The standard beta distribution has A=0 and B=1.
360     Fractional error less than 3.0e-7.
361     }
362    
363     {BETAINV}
364     function BetaInv(Probability, Alpha, Beta, A, B : Single) : Single;
365     {-Returns the inverse of the cumulative beta probability density function.
366     That is, if Probability = BetaDist(X,...), then
367     BetaInv(Probability,...) = X.
368     Probability is a probability (0 <= p <= 1) associated with the
369     beta distribution.
370     Alpha is a parameter to the distribution.
371     Beta is a parameter to the distribution.
372     A is the lower bound to the interval of the distribution.
373     B is the upper bound to the interval of the distribution.
374     Fractional error less than 3.0e-7.
375     }
376    
377     {BINOMDIST}
378     function BinomDist(NumberS, Trials : Integer; ProbabilityS : Single;
379     Cumulative : Boolean) : Single;
380     {-Returns the individual term binomial distribution probability.
381     Use BinomDist in problems with a fixed number of tests or Trials,
382     when the outcomes of any trial are only success or failure,
383     when Trials are independent, and when the probability of success is
384     constant throughout the experiment.
385     NumberS is the number of successes in Trials.
386     Trials is the number of independent trials.
387     ProbabilityS is the probability of success on each trial.
388     Cumulative is a logical value that determines the form of the function.
389     If Cumulative is TRUE, then BinomDist returns the cumulative
390     distribution function, which is the probability that there are at most
391     NumberS successes; if FALSE, it returns the probability mass function,
392     which is the probability that there are NumberS successes.
393     }
394    
395     {CRITBINOM}
396     function CritBinom(Trials : Integer; ProbabilityS, Alpha : Single) : Integer;
397     {-Returns the smallest value for which the cumulative binomial distribution
398     is greater than or equal to a criterion value.
399     Trials is the number of Bernoulli trials.
400     ProbabilityS is the probability of a success on each trial.
401     Alpha is the criterion value.
402     }
403    
404     {CHIDIST}
405     function ChiDist(X : Single; DegreesFreedom : Integer) : Single;
406     {-Returns the one-tailed probability of the chi-squared distribution.
407     The chi-squared distribution is associated with a chi-squared test.
408     Use the chi-squared test to compare observed and expected values.
409     X is the value at which you want to evaluate the distribution.
410     DegreesFreedom is the number of degrees of freedom.
411     }
412    
413     {CHIINV}
414     function ChiInv(Probability : Single; DegreesFreedom : Integer) : Single;
415     {-Returns the inverse of the one-tailed probability of the chi-squared
416     distribution. If Probability = ChiDist(X,...), then
417     ChiInv(Probability,...) = X.
418     Probability is a probability associated with the chi-squared
419     distribution.
420     DegreesFreedom is the number of degrees of freedom.
421     }
422    
423     {EXPONDIST}
424     function ExponDist(X, Lambda : Single; Cumulative : Boolean) : Single;
425     {-Returns the exponential distribution. Use ExponDist to model the time
426     between events.
427     X is the value of the function.
428     Lambda is the parameter value.
429     Cumulative is a logical value that indicates which form of the
430     exponential function to provide. If Cumulative is TRUE, ExponDist
431     returns the cumulative distribution function; if FALSE, it returns
432     the probability density function.
433     }
434    
435     {FDIST}
436     function FDist(X : Single; DegreesFreedom1, DegreesFreedom2 : Integer) : Single;
437     {-Returns the F probability distribution. You can use this function to
438     determine whether two data sets have different degrees of diversity.
439     X is the value at which to evaluate the function.
440     DegreesFreedom1 is the numerator degrees of freedom.
441     DegreesFreedom2 is the denominator degrees of freedom.
442     Fractional error less than 3.0e-7.
443     }
444    
445     {FINV}
446     function FInv(Probability : Single;
447     DegreesFreedom1, DegreesFreedom2 : Integer) : Single;
448     {-Returns the inverse of the F probability distribution. If
449     p = FDist(X,...), then FInv(p,...) = X.
450     Probability is a probability associated with the F cumulative
451     distribution.
452     DegreesFreedom1 is the numerator degrees of freedom.
453     DegreesFreedom2 is the denominator degrees of freedom.
454     Fractional error less than 3.0e-7.
455     }
456    
457     {LOGNORMDIST}
458     function LogNormDist(X, Mean, StandardDev : Single) : Single;
459     {-Returns the cumulative lognormal distribution of X, where ln(X) is
460     normally distributed with parameters Mean and StandardDev.
461     Use this function to analyze data that has been logarithmically
462     transformed.
463     X is the value at which to evaluate the function.
464     Mean is the mean of ln(X).
465     StandardDev is the standard deviation of ln(X).
466     }
467    
468     {LOGINV}
469     function LogInv(Probability, Mean, StandardDev : Single) : Single;
470     {-Returns the inverse of the lognormal cumulative distribution function of
471     X, where ln(X) is normally distributed with parameters Mean and
472     StandardDev. If p = LogNormDist(X,...) then LogInv(p,...) = X.
473     Probability is a probability associated with the lognormal distribution.
474     Mean is the mean of ln(X).
475     StandardDev is the standard deviation of ln(X).
476     }
477    
478     {NORMDIST}
479     function NormDist(X, Mean, StandardDev : Single; Cumulative : Boolean) : Single;
480     {-Returns the normal cumulative distribution for the specified Mean and
481     standard deviation.
482     X is the value for which you want the distribution.
483     Mean is the arithmetic mean of the distribution.
484     StandardDev is the standard deviation of the distribution.
485     Cumulative is a logical value that determines the form of the function.
486     If Cumulative is TRUE, NormDist returns the cumulative distribution
487     function; if FALSE, it returns the probability density function.
488     }
489    
490     {NORMINV}
491     function NormInv(Probability, Mean, StandardDev : Single) : Single;
492     {-Returns the inverse of the normal cumulative distribution for the
493     specified mean and standard deviation.
494     Probability is a probability corresponding to the normal distribution.
495     Mean is the arithmetic mean of the distribution.
496     StandardDev is the standard deviation of the distribution.
497     }
498    
499     {NORMSDIST}
500     function NormSDist(Z : Single) : Single;
501     {-Returns the standard normal cumulative distribution function.
502     The distribution has a mean of 0 (zero) and a standard deviation of one.
503     Z is the value for which you want the distribution.
504     }
505    
506     {NORMSINV}
507     function NormSInv(Probability : Single) : Single;
508     {-Returns the inverse of the standard normal cumulative distribution.
509     The distribution has a mean of zero and a standard deviation of one.
510     Probability is a probability corresponding to the normal distribution.
511     }
512    
513     {POISSON}
514     function Poisson(X : Integer; Mean : Single; Cumulative : Boolean) : Single;
515     {-Returns the Poisson distribution.
516     X is the number of events.
517     Mean is the expected numeric value.
518     Cumulative is a logical value that determines the form of the
519     probability distribution returned. If Cumulative is TRUE, Poisson
520     returns the cumulative Poisson probability that the number of random
521     events occurring will be between zero and X inclusive; if FALSE,
522     it returns the Poisson probability mass function that the number of
523     events occurring will be exactly X.
524     }
525    
526     {TDIST}
527     function TDist(X : Single; DegreesFreedom : Integer; TwoTails : Boolean) : Single;
528     {-Returns the Student's t-distribution. The t-distribution is used in the
529     hypothesis testing of small sample data sets. Use this function in place
530     of a table of critical values for the t-distribution.
531     X is the numeric value at which to evaluate the distribution.
532     DegreesFreedom is an Integer indicating the number of degrees of freedom.
533     TwoTails if a logical value that indicates the number of distribution
534     tails to return. If FALSE, TDist returns the one-tailed distribution;
535     otherwise it returns the two-tailed distribution.
536     }
537    
538     {TINV}
539     function TInv(Probability : Single; DegreesFreedom : Integer) : Single;
540     {-Returns the inverse of the Student's t-distribution for the specified
541     degrees of freedom.
542     Probability is the probability associated with the two-tailed Student's
543     t-distribution.
544     DegreesFreedom is the number of degrees of freedom to characterize
545     the distribution.
546     }
547    
548     {--------------------------------------------------------------------------}
549     {undocumented functions you can call if you need}
550    
551     function Erfc(X : Single) : Single;
552     {-Returns the complementary error function with fractional error
553     everywhere less than 1.2e-7. X is any finite value.
554     }
555    
556     function GammaLn(X : Single) : Single;
557     {-Returns ln(Gamma(X)) where X > 0.0.}
558    
559     {--------------------------------------------------------------------------}
560    
561     {.$DEFINE Debug}
562     {$IFDEF Debug}
563     {like Largest and Smallest but using slower simpler algorithm}
564     function LargestSort(const Data: array of Double; K : Integer) : Double;
565     function SmallestSort(const Data: array of double; K : Integer) : Double;
566     {$ENDIF}
567    
568     implementation
569    
570     procedure RaiseStatError(Code : LongInt);
571     {-Generate a statistics exception}
572     var
573     E : EStStatError;
574     begin
575     E := EStStatError.CreateResTP(Code, 0);
576     E.ErrorCode := Code;
577     raise E;
578     end;
579    
580     procedure DoubleArraySort(var Data; NData : Integer);
581     {-Heapsort an array of Doubles into Ascending order}
582     type
583     TDoubleArray1 = array[1..StMaxBlockSize div SizeOf(Double)] of Double;
584     var
585     i : Integer;
586     T : Double;
587     DA : TDoubleArray1 absolute Data;
588    
589     procedure Adjust(i, N : Integer);
590     var
591     j : Integer;
592     S : Double;
593     begin
594     {j is left child of i}
595     j := 2*i;
596     {save i'th element temporarily}
597     S := DA[i];
598     while (j <= N) do begin
599     {compare left and right child}
600     if (j < N) and (DA[j] < DA[j+1]) then
601     {j indexes larger child}
602     inc(j);
603     if (S >= DA[j]) then
604     {a position for item is found}
605     break;
606     {move the larger child up a level}
607     DA[j shr 1] := DA[j];
608     {look at left child of j}
609     j := j shl 1;
610     end;
611     {store saved item}
612     DA[j shr 1] := S;
613     end;
614    
615     begin
616     {transform the elements into a heap}
617     for i := (NData shr 1) downto 1 do
618     Adjust(i, NData);
619    
620     {repeatedly exchange the maximum at top of heap with the last element}
621     for i := NData downto 2 do begin
622     T := DA[1];
623     DA[1] := DA[i];
624     DA[i] := T;
625     {update the heap for the remaining elements}
626     Adjust(1, i-1);
627     end;
628     end;
629    
630     function CopyAndSort(const Data; NData : Integer;
631     var SD : PDoubleArray) : Cardinal;
632     {-Allocates heap space for an array copy, moves data, sorts, and returns size}
633     var
634     Size : LongInt;
635     begin
636     Size := LongInt(NData)*sizeof(Double);
637     {if (Size > MaxBlockSize) then}
638     { RaiseStatError(stscStatBadCount);}
639     Result := Size;
640     getmem(SD, Size); {raises exception if insufficient memory}
641     try
642     move(Data, SD^, Size);
643     DoubleArraySort(SD^, NData);
644     except
645     freemem(SD, Size);
646     raise;
647     end;
648     end;
649    
650     function AveDev(const Data: array of Double) : Double;
651     begin
652     Result := AveDev16(Data, High(Data)+1);
653     end;
654    
655     function Mean(const Data; NData : Integer) : Extended;
656     {-Computes the mean of an array of Doubles}
657     var
658     i : Integer;
659     s : Extended;
660     begin
661     s := 0.0;
662     for I := 0 to NData-1 do
663     s := s+TDoubleArray(Data)[I];
664     Result := s/NData;
665     end;
666    
667     function AveDev16(const Data; NData : Integer) : Double;
668     var
669     i : Integer;
670     m, s : Extended;
671     begin
672     if (NData <= 0) then
673     RaiseStatError(stscStatBadCount);
674    
675     {compute sum of absolute deviations}
676     m := Mean(Data, NData);
677     s := 0.0;
678     for i := 0 to NData-1 do
679     s := s+abs(TDoubleArray(Data)[i]-m);
680    
681     Result := s/NData;
682     end;
683    
684     function Confidence(Alpha, StandardDev : Double; Size : LongInt) : Double;
685     begin
686     if (StandardDev <= 0) or (Size < 1) then
687     RaiseStatError(stscStatBadParam);
688     Result := NormSInv(1.0-Alpha/2.0)*StandardDev/sqrt(Size);
689     end;
690    
691     function Correlation(const Data1, Data2 : array of Double) : Double;
692     begin
693     if (High(Data1) <> High(Data2)) then
694     RaiseStatError(stscStatBadCount);
695     Result := Correlation16(Data1, Data2, High(Data1)+1);
696     end;
697    
698     function Correlation16(const Data1, Data2; NData : Integer) : Double;
699     var
700     sx, sy, xmean, ymean, sxx, sxy, syy, x, y : Extended;
701     i : Integer;
702     begin
703     if (NData <= 1) then
704     RaiseStatError(stscStatBadCount);
705    
706     {compute basic sums}
707     sx := 0.0;
708     sy := 0.0;
709     sxx := 0.0;
710     sxy := 0.0;
711     syy := 0.0;
712     for i := 0 to NData-1 do begin
713     x := TDoubleArray(Data1)[i];
714     y := TDoubleArray(Data2)[i];
715     sx := sx+x;
716     sy := sy+y;
717     sxx := sxx+x*x;
718     syy := syy+y*y;
719     sxy := sxy+x*y;
720     end;
721     xmean := sx/NData;
722     ymean := sy/NData;
723     sxx := sxx-NData*xmean*xmean;
724     syy := syy-NData*ymean*ymean;
725     sxy := sxy-NData*xmean*ymean;
726    
727     Result := sxy/sqrt(sxx*syy);
728     end;
729    
730     function Covariance(const Data1, Data2 : array of Double) : Double;
731     begin
732     if (High(Data1) <> High(Data2)) then
733     RaiseStatError(stscStatBadCount);
734     Result := Covariance16(Data1, Data2, High(Data1)+1);
735     end;
736    
737     function Covariance16(const Data1, Data2; NData : Integer) : Double;
738     var
739     sx, sy, xmean, ymean, sxy, x, y : Extended;
740     i : Integer;
741     begin
742     if (NData <= 1) then
743     RaiseStatError(stscStatBadCount);
744    
745     {compute basic sums}
746     sx := 0.0;
747     sy := 0.0;
748     sxy := 0.0;
749     for i := 0 to NData-1 do begin
750     x := TDoubleArray(Data1)[i];
751     y := TDoubleArray(Data2)[i];
752     sx := sx+x;
753     sy := sy+y;
754     sxy := sxy+x*y;
755     end;
756     xmean := sx/NData;
757     ymean := sy/NData;
758     sxy := sxy-NData*xmean*ymean;
759    
760     Result := sxy/NData;
761     end;
762    
763     function DevSq(const Data: array of Double) : Double;
764     begin
765     Result := DevSq16(Data, High(Data)+1);
766     end;
767    
768     function DevSq16(const Data; NData : Integer) : Double;
769     var
770     i : Integer;
771     sx, sxx, x : Extended;
772     begin
773     if (NData <= 0) then
774     RaiseStatError(stscStatBadCount);
775    
776     sx := 0.0;
777     sxx := 0.0;
778     for i := 0 to NData-1 do begin
779     x := TDoubleArray(Data)[i];
780     sx := sx+x;
781     sxx := sxx+x*x;
782     end;
783     Result := sxx-sqr(sx)/NData;
784     end;
785    
786     procedure Frequency(const Data: array of Double; const Bins: array of Double;
787     var Counts: array of LongInt);
788     begin
789     if (High(Counts) <= High(Bins)) then
790     RaiseStatError(stscStatBadCount);
791     Frequency16(Data, High(Data)+1, Bins, High(Bins)+1, Counts);
792     end;
793    
794     procedure Frequency16(const Data; NData : Integer; const Bins; NBins : Integer;
795     var Counts);
796     var
797     b, i : Integer;
798     Size : Cardinal;
799     SD : PDoubleArray;
800     begin
801     if (NData <= 0) or (NBins <= 0) then
802     RaiseStatError(stscStatBadCount);
803    
804     {copy and sort array}
805     Size := CopyAndSort(Data, NData, SD);
806     try
807     {initialize all counts to zero}
808     fillchar(Counts, (NBins+1)*sizeof(Integer), 0);
809    
810     {scan all data elements, putting into correct bin}
811     b := 0;
812     i := 0;
813     while (i < NData) do begin
814     if (SD^[i] <= TDoubleArray(Bins)[b]) then begin
815     {current data element falls into this bin}
816     inc(TIntArray(Counts)[b]);
817     inc(i);
818     end else begin
819     {move to next bin that collects data}
820     repeat
821     inc(b);
822     until (b = NBins) or (TDoubleArray(Bins)[b] > SD^[i]);
823     if (b = NBins) then begin
824     {add remaining elements to the catchall bin}
825     inc(TIntArray(Counts)[b], NData-i);
826     i := NData;
827     end;
828     end;
829     end;
830    
831     finally
832     freemem(SD, Size);
833     end;
834     end;
835    
836     function GeometricMean(const Data: array of Double) : Double;
837     begin
838     Result := GeometricMean16(Data, High(Data)+1);
839     end;
840    
841     function GeometricMean16(const Data; NData : Integer) : Double;
842     var
843     i : Integer;
844     s, t : Extended;
845     begin
846     if (NData <= 0) then
847     RaiseStatError(stscStatBadCount);
848    
849     s := 1.0;
850     for i := 0 to NData-1 do begin
851     t := TDoubleArray(Data)[i];
852     if (t <= 0.0) then
853     RaiseStatError(stscStatBadData);
854     s := s*t;
855     end;
856    
857     Result := Power(s, 1.0/NData);
858     end;
859    
860     function HarmonicMean(const Data: array of Double) : Double;
861     begin
862     Result := HarmonicMean16(Data, High(Data)+1);
863     end;
864    
865     function HarmonicMean16(const Data; NData : Integer) : Double;
866     var
867     i : Integer;
868     s, t : Extended;
869     begin
870     if (NData <= 0) then
871     RaiseStatError(stscStatBadCount);
872    
873     s := 0.0;
874     for i := 0 to NData-1 do begin
875     t := TDoubleArray(Data)[i];
876     if (t = 0.0) then
877     RaiseStatError(stscStatBadData);
878     s := s+(1.0/t);
879     end;
880     Result := NData/s;
881     end;
882    
883     function Largest(const Data: array of Double; K : Integer) : Double;
884     begin
885     Result := Largest16(Data, High(Data)+1, K);
886     end;
887    
888     function Largest16(const Data; NData : Integer; K : Integer) : Double;
889     var
890     b, t, i, j : integer;
891     Size : LongInt;
892     temp, pval : Double;
893     SD : PDoubleArray;
894     begin
895     if (NData <= 0) then
896     RaiseStatError(stscStatBadCount);
897     if (K <= 0) or (K > NData) then
898     RaiseStatError(stscStatBadParam);
899    
900     Size := LongInt(NData)*sizeof(Double);
901     {if (Size > MaxBlockSize) then}
902     { RaiseStatError(stscStatBadCount);}
903     getmem(SD, Size); {raises exception if insufficient memory}
904     try
905     move(Data, SD^, Size);
906    
907     {make K 0-based}
908     dec(K);
909    
910     {use quicksort-like selection}
911     b := 0;
912     t := NData-1;
913     while (t > b) do begin
914     {use random pivot in case of already-sorted data}
915     pval := SD^[b+random(t-b+1)];
916     i := b;
917     j := t;
918     repeat
919     while (SD^[i] > pval) do
920     inc(i);
921     while (pval > SD^[j]) do
922     dec(j);
923     if (i <= j) then begin
924     temp := SD^[i];
925     SD^[i] := SD^[j];
926     SD^[j] := temp;
927     inc(i);
928     dec(j);
929     end;
930     until (i > j);
931     if (j < K) then
932     b := i;
933     if (K < i) then
934     t := j;
935     end;
936     Result := SD^[K];
937    
938     finally
939     freemem(SD, Size);
940     end;
941     end;
942    
943     {debug version of Largest: slower but simpler}
944     {$IFDEF Debug}
945     function LargestSort(const Data: array of Double; K : Integer) : Double;
946     var
947     Size : Cardinal;
948     NData : Integer;
949     SD : PDoubleArray;
950     begin
951     NData := High(Data)+1;
952     if (NData <= 0) then
953     RaiseStatError(stscStatBadCount);
954     if (K <= 0) or (K > NData) then
955     RaiseStatError(stscStatBadParam);
956    
957     {copy and sort array}
958     Size := CopyAndSort(Data, NData, SD);
959     try
960     {K=1 returns largest value, K=NData returns smallest}
961     Result := SD^[NData-K];
962     finally
963     freemem(SD, Size);
964     end;
965     end;
966     {$ENDIF}
967    
968     function Median(const Data: array of Double) : Double;
969     begin
970     Result := Median16(Data, High(Data)+1);
971     end;
972    
973     function Median16(const Data; NData : Integer) : Double;
974     var
975     m : Integer;
976     begin
977     if (NData <= 0) then
978     RaiseStatError(stscStatBadCount);
979    
980     m := NData shr 1;
981     if odd(NData) then
982     Result := Largest16(Data, NData, m+1)
983     else
984     Result := (Largest16(Data, NData, m+1)+Largest16(Data, NData, m))/2.0;
985     end;
986    
987     function Mode(const Data: array of Double) : Double;
988     begin
989     Result := Mode16(Data, High(Data)+1);
990     end;
991    
992     function Mode16(const Data; NData : Integer) : Double;
993     var
994     maxf, i, f : Integer;
995     Size : Cardinal;
996     last, max : Double;
997     SD : PDoubleArray;
998     begin
999     if (NData <= 0) then
1000     RaiseStatError(stscStatBadCount);
1001    
1002     {copy and sort array}
1003     Size := CopyAndSort(Data, NData, SD);
1004     try
1005     {find the value with highest frequency}
1006     last := SD^[0];
1007     max := last;
1008     f := 1;
1009     maxf := f;
1010    
1011     for i := 1 to NData-1 do begin
1012     if SD^[i] = last then
1013     {keep count of identical values}
1014     inc(f)
1015     else begin
1016     {start a new series}
1017     if f > maxf then begin
1018     max := last;
1019     maxf := f;
1020     end;
1021     last := SD^[i];
1022     f := 1;
1023     end;
1024     end;
1025    
1026     {test last group}
1027     if f > maxf then
1028     max := last;
1029    
1030     Result := max;
1031     finally
1032     freemem(SD, Size);
1033     end;
1034     end;
1035    
1036     function Percentile(const Data: array of Double; K : Double) : Double;
1037     begin
1038     Result := Percentile16(Data, High(Data)+1, K);
1039     end;
1040    
1041     function Percentile16(const Data; NData : Integer; K : Double) : Double;
1042     const
1043     eps = 1.0e-10;
1044     var
1045     ibin : Integer;
1046     Size : Cardinal;
1047     rbin, l, h : Double;
1048     SD : PDoubleArray;
1049     begin
1050     if (NData <= 0) then
1051     RaiseStatError(stscStatBadCount);
1052     if (K < 0.0) or (K > 1.0) then
1053     RaiseStatError(stscStatBadParam);
1054    
1055     {copy and sort array}
1056     Size := CopyAndSort(Data, NData, SD);
1057     try
1058     {find nearest bins}
1059     rbin := K*(NData-1);
1060     ibin := Trunc(rbin);
1061     if Frac(rbin) < eps then
1062     {very close to array index below}
1063     Result := SD^[ibin]
1064     else if (Int(rbin)+1.0-rbin) < eps then
1065     {very close to array index above}
1066     Result := SD^[ibin+1]
1067     else begin
1068     {need to interpolate between two bins}
1069     l := SD^[ibin];
1070     h := SD^[ibin+1];
1071     Result := l+(h-l)*(K*(NData-1)-ibin);
1072     end;
1073     finally
1074     freemem(SD, Size);
1075     end;
1076     end;
1077    
1078     function PercentRank(const Data: array of Double; X : Double) : Double;
1079     begin
1080     Result := PercentRank16(Data, High(Data)+1, X);
1081     end;
1082    
1083     function PercentRank16(const Data; NData : Integer; X : Double) : Double;
1084     var
1085     b, t, m : Integer;
1086     Size : Cardinal;
1087     SD : PDoubleArray;
1088     begin
1089     if (NData <= 0) then
1090     RaiseStatError(stscStatBadCount);
1091    
1092     {copy and sort array}
1093     Size := CopyAndSort(Data, NData, SD);
1094     try
1095     {test end conditions}
1096     if (X < SD^[0]) or (X > SD^[NData-1]) then
1097     RaiseStatError(stscStatBadParam);
1098    
1099     {find nearby bins using binary search}
1100     b := 0;
1101     t := NData-1;
1102     while (t-b) > 1 do begin
1103     m := (b+t) shr 1;
1104     if (X >= SD^[m]) then
1105     {search upper half}
1106     b := m
1107     else
1108     {search lower half}
1109     t := m;
1110     end;
1111    
1112     {now X is known to be between b (inclusive) and b+1}
1113     {handle duplicate elements below b}
1114     while (b > 0) and (SD^[b-1] = X) do
1115     dec(b);
1116    
1117     if (SD^[b] = X) then
1118     {an exact match}
1119     Result := b/(NData-1)
1120     else
1121     {interpolate}
1122     Result := (b+(X-SD^[b])/(SD^[b+1]-SD^[b]))/(NData-1);
1123    
1124     finally
1125     freemem(SD, Size);
1126     end;
1127     end;
1128    
1129     const
1130     sqrt2pi = 2.5066282746310005; {sqrt(2*pi)}
1131    
1132     function GammaLn(X : Single) : Single;
1133     {-Returns ln(Gamma(X)) where X > 0}
1134     const
1135     cof : array[0..5] of Double = (
1136     76.18009172947146, -86.50532032941677, 24.01409824083091,
1137     -1.231739572450155, 0.1208650973866179e-2, -0.5395239384953e-5);
1138     var
1139     y, tmp, ser : Double;
1140     j : Integer;
1141     begin
1142     if (X <= 0) then
1143     RaiseStatError(stscStatBadParam);
1144    
1145     y := X;
1146     tmp := X+5.5;
1147     tmp := tmp-(X+0.5)*ln(tmp);
1148     ser := 1.000000000190015;
1149     for j := low(cof) to high(cof) do begin
1150     y := y+1.0;
1151     ser := ser+cof[j]/y;
1152     end;
1153     Result := -tmp+ln(sqrt2pi*ser/X);
1154     end;
1155    
1156     const
1157     MFactLnA = 65;
1158     var
1159     FactLnA : array[2..MFactLna] of Single; {lookup table of FactLn values}
1160    
1161     function FactLn(N : Integer) : Single;
1162     {-Returns ln(N!) for N >= 0}
1163     begin
1164     if (N <= 1) then
1165     Result := 0.0
1166     else if (N <= MFactLnA) then
1167     {use lookup table}
1168     Result := FactLnA[N]
1169     else
1170     {compute each time}
1171     Result := GammaLn(N+1.0);
1172     end;
1173    
1174     const
1175     MFactA = 33;
1176     var
1177     FactA : array[2..MFactA] of Double; {lookup table of factorial values}
1178    
1179     function Factorial(N : Integer) : Extended;
1180     begin
1181     if (N < 0) then
1182     RaiseStatError(stscStatBadParam);
1183    
1184     if (N <= 1) then
1185     Result := 1.0
1186     else if (N <= MFactA) then
1187     {use lookup table}
1188     Result := FactA[N]
1189     else
1190     {bigger than lookup table allows. may overflow!}
1191     Result := exp(GammaLn(N+1.0))
1192     end;
1193    
1194     function Permutations(Number, NumberChosen : Integer) : Extended;
1195     begin
1196     if (Number < 0) or (NumberChosen < 0) or (Number < NumberChosen) then
1197     RaiseStatError(stscStatBadParam);
1198     {the 0.5 and Int function clean up roundoff error for smaller N and K}
1199     Result := Int(0.5+exp(FactLn(Number)-FactLn(Number-NumberChosen)));
1200     end;
1201    
1202     function Combinations(Number, NumberChosen : Integer) : Extended;
1203     begin
1204     if (Number < 0) or (NumberChosen < 0) or (Number < NumberChosen) then
1205     RaiseStatError(stscStatBadParam);
1206     {the 0.5 and Int function clean up roundoff error for smaller N and K}
1207     Result := Int(0.5+exp(FactLn(Number)-FactLn(NumberChosen)
1208     -FactLn(Number-NumberChosen)));
1209     end;
1210    
1211     function Rank(Number: Double; const Data: array of Double;
1212     Ascending: Boolean) : Integer;
1213     begin
1214     Result := Rank16(Number, Data, High(Data)+1, Ascending);
1215     end;
1216    
1217     function Rank16(Number: Double; const Data; NData : Integer;
1218     Ascending: Boolean) : Integer;
1219     var
1220     r : Integer;
1221     begin
1222     if (NData <= 0) then
1223     RaiseStatError(stscStatBadCount);
1224    
1225     {Data not known to be sorted, so must search linearly}
1226     if (Ascending) then begin
1227     for r := 0 to NData-1 do
1228     if TDoubleArray(Data)[r] = Number then begin
1229     Result := r+1;
1230     exit;
1231     end;
1232     end else begin
1233     for r := NData-1 downto 0 do
1234     if TDoubleArray(Data)[r] = Number then begin
1235     Result := NData-r;
1236     exit;
1237     end;
1238     end;
1239     Result := 0;
1240     end;
1241    
1242     function Smallest(const Data: array of Double; K : Integer) : Double;
1243     begin
1244     Result := Smallest16(Data, High(Data)+1, K);
1245     end;
1246    
1247     function Smallest16(const Data; NData : Integer; K : Integer) : Double;
1248     var
1249     b, t, i, j : integer;
1250     Size : LongInt;
1251     temp, pval : Double;
1252     SD : PDoubleArray;
1253     begin
1254     if (NData <= 0) then
1255     RaiseStatError(stscStatBadCount);
1256     if (K <= 0) or (K > NData) then
1257     RaiseStatError(stscStatBadParam);
1258    
1259     Size := LongInt(NData)*sizeof(Double);
1260     {if (Size > MaxBlockSize) then}
1261     { RaiseStatError(stscStatBadCount);}
1262     getmem(SD, Size); {raises exception if insufficient memory}
1263     try
1264     move(Data, SD^, Size);
1265    
1266     {make K 0-based}
1267     dec(K);
1268     {use quicksort-like selection}
1269     b := 0;
1270     t := NData-1;
1271     while (t > b) do begin
1272     {use random pivot in case of already-sorted data}
1273     pval := SD^[b+random(t-b+1)];
1274     i := b;
1275     j := t;
1276     repeat
1277     while (SD^[i] < pval) do
1278     inc(i);
1279     while (pval < SD^[j]) do
1280     dec(j);
1281     if (i <= j) then begin
1282     temp := SD^[i];
1283     SD^[i] := SD^[j];
1284     SD^[j] := temp;
1285     inc(i);
1286     dec(j);
1287     end;
1288     until (i > j);
1289    
1290     if (j < K) then
1291     b := i;
1292     if (K < i) then
1293     t := j;
1294     end;
1295     Result := SD^[K];
1296     finally
1297     freemem(SD, Size);
1298     end;
1299     end;
1300    
1301     {debug version of Smallest: slower but simpler}
1302     {$IFDEF Debug}
1303     function SmallestSort(const Data: array of double; K : Integer) : Double;
1304     var
1305     Size : Cardinal;
1306     NData : Integer;
1307     SD : PDoubleArray;
1308     begin
1309     NData := High(Data)+1;
1310     if (NData <= 0) then
1311     RaiseStatError(stscStatBadCount);
1312     if (K <= 0) or (K > NData) then
1313     RaiseStatError(stscStatBadParam);
1314    
1315     {copy and sort array}
1316     Size := CopyAndSort(Data, NData, SD);
1317     try
1318     {K=1 returns smallest value, K=NData returns largest}
1319     Result := SD^[K-1];
1320     finally
1321     freemem(SD, Size);
1322     end;
1323     end;
1324     {$ENDIF}
1325    
1326     function TrimMean(const Data: array of Double; Percent : Double) : Double;
1327     begin
1328     Result := TrimMean16(Data, High(Data)+1, Percent);
1329     end;
1330    
1331     function TrimMean16(const Data; NData : Integer; Percent : Double) : Double;
1332     var
1333     ntrim : Integer;
1334     Size : Cardinal;
1335     SD : PDoubleArray;
1336     begin
1337     if (NData <= 0) then
1338     RaiseStatError(stscStatBadCount);
1339     if (Percent < 0.0) or (Percent > 1.0) then
1340     RaiseStatError(stscStatBadParam);
1341    
1342     {compute total number of trimmed points, rounding down to an even number}
1343     ntrim := trunc(Percent*NData);
1344     if odd(ntrim) then
1345     dec(ntrim);
1346    
1347     {take the easy way out when possible}
1348     if (ntrim = 0) then begin
1349     Result := Mean(Data, NData);
1350     exit;
1351     end;
1352    
1353     {copy and sort array}
1354     Size := CopyAndSort(Data, NData, SD);
1355     try
1356     {return Mean of remaining data points}
1357     Result := Mean(SD^[ntrim shr 1], NData-ntrim);
1358     finally
1359     freemem(SD, Size);
1360     end;
1361     end;
1362    
1363     {------------------------------------------------------------------------}
1364    
1365     procedure LinEst(const KnownY: array of Double;
1366     const KnownX: array of Double; var LF : TStLinEst; ErrorStats : Boolean);
1367     begin
1368     if (High(KnownY) <> High(KnownX)) then
1369     RaiseStatError(stscStatBadCount);
1370     LinEst16(KnownY, KnownX, High(KnownY)+1, LF, ErrorStats);
1371     end;
1372    
1373     procedure LinEst16(const KnownY; const KnownX; NData : Integer;
1374     var LF : TStLinEst; ErrorStats : Boolean);
1375     var
1376     i : Integer;
1377     sx, sy, xmean, ymean, sxx, sxy, syy, x, y : Extended;
1378     begin
1379     if (NData <= 2) then
1380     RaiseStatError(stscStatBadCount);
1381    
1382     {compute basic sums}
1383     sx := 0.0;
1384     sy := 0.0;
1385     sxx := 0.0;
1386     sxy := 0.0;
1387     syy := 0.0;
1388     for i := 0 to NData-1 do begin
1389     x := TDoubleArray(KnownX)[i];
1390     y := TDoubleArray(KnownY)[i];
1391     sx := sx+x;
1392     sy := sy+y;
1393     sxx := sxx+x*x;
1394     syy := syy+y*y;
1395     sxy := sxy+x*y;
1396     end;
1397     xmean := sx/NData;
1398     ymean := sy/NData;
1399     sxx := sxx-NData*xmean*xmean;
1400     syy := syy-NData*ymean*ymean;
1401     sxy := sxy-NData*xmean*ymean;
1402    
1403     {check for zero variance}
1404     if (sxx <= 0.0) or (syy <= 0.0) then
1405     RaiseStatError(stscStatBadData);
1406    
1407     {initialize returned parameters}
1408     fillchar(LF, sizeof(LF), 0);
1409    
1410     {regression coefficients}
1411     LF.B1 := sxy/sxx;
1412     LF.B0 := ymean-LF.B1*xmean;
1413    
1414     {error statistics}
1415     if (ErrorStats) then begin
1416     LF.ssr := LF.B1*sxy;
1417     LF.sse := syy-LF.ssr;
1418     LF.R2 := LF.ssr/syy;
1419     LF.df := NData-2;
1420     LF.sigma := sqrt(LF.sse/LF.df);
1421     if LF.sse = 0.0 then
1422     {pick an arbitrarily large number for perfect fit}
1423     LF.F0 := 1.7e+308
1424     else
1425     LF.F0 := (LF.ssr*LF.df)/LF.sse;
1426     LF.seB1 := LF.sigma/sqrt(sxx);
1427     LF.seB0 := LF.sigma*sqrt((1.0/NData)+(xmean*xmean/sxx));
1428     end;
1429     end;
1430    
1431     procedure LogEst(const KnownY: array of Double;
1432     const KnownX: array of Double; var LF : TStLinEst; ErrorStats : Boolean);
1433     begin
1434     if (High(KnownY) <> High(KnownX)) then
1435     RaiseStatError(stscStatBadCount);
1436     LogEst16(KnownY, KnownX, High(KnownY)+1, LF, ErrorStats);
1437     end;
1438    
1439     procedure LogEst16(const KnownY; const KnownX; NData : Integer;
1440     var LF : TStLinEst; ErrorStats : Boolean);
1441     var
1442     i : Integer;
1443     Size : LongInt;
1444     lny : PDoubleArray;
1445     begin
1446     if (NData <= 2) then
1447     RaiseStatError(stscStatBadCount);
1448    
1449     {allocate array for the log-transformed data}
1450     Size := LongInt(NData)*sizeof(Double);
1451     {f (Size > MaxBlockSize) then}
1452     { RaiseStatError(stscStatBadCount);}
1453     getmem(lny, Size);
1454     try
1455     {initialize transformed data}
1456     for i := 0 to NData-1 do
1457     lny^[i] := ln(TDoubleArray(KnownY)[i]);
1458    
1459     {fit transformed data}
1460     LinEst16(lny^, KnownX, NData, LF, ErrorStats);
1461    
1462     {return values for B0 and B1 in exponential model y=B0*B1^x}
1463     LF.B0 := exp(LF.B0);
1464     LF.B1 := exp(LF.B1);
1465     {leave other values in LF in log form}
1466     finally
1467     freemem(lny, Size);
1468     end;
1469     end;
1470    
1471     function Forecast(X : Double; const KnownY: array of Double;
1472     const KnownX: array of Double) : Double;
1473     begin
1474     if (High(KnownY) <> High(KnownX)) then
1475     RaiseStatError(stscStatBadCount);
1476     Result := Forecast16(X, KnownY, KnownX, High(KnownY)+1);
1477     end;
1478    
1479     function Forecast16(X : Double; const KnownY; const KnownX;
1480     NData : Integer) : Double;
1481     var
1482     LF : TStLinEst;
1483     begin
1484     LinEst16(KnownY, KnownX, NData, LF, false);
1485     Result := LF.B0+LF.B1*X;
1486     end;
1487    
1488     function ForecastExponential(X : Double; const KnownY: array of Double;
1489     const KnownX: array of Double) : Double;
1490     begin
1491     if (High(KnownY) <> High(KnownX)) then
1492     RaiseStatError(stscStatBadCount);
1493     Result := ForecastExponential16(X, KnownY, KnownX, High(KnownY)+1);
1494     end;
1495    
1496     function ForecastExponential16(X : Double; const KnownY; const KnownX;
1497     NData : Integer) : Double;
1498     var
1499     LF : TStLinEst;
1500     begin
1501     LogEst16(KnownY, KnownX, NData, LF, false);
1502     Result := LF.B0*Power(LF.B1, X);
1503     end;
1504    
1505     function Intercept(const KnownY: array of Double;
1506     const KnownX: array of Double) : Double;
1507     begin
1508     if (High(KnownY) <> High(KnownX)) then
1509     RaiseStatError(stscStatBadCount);
1510     Result := Intercept16(KnownY, KnownX, High(KnownY)+1);
1511     end;
1512    
1513     function Intercept16(const KnownY; const KnownX; NData : Integer) : Double;
1514     var
1515     LF : TStLinEst;
1516     begin
1517     LinEst16(KnownY, KnownX, NData, LF, false);
1518     Result := LF.B0;
1519     end;
1520    
1521     function RSquared(const KnownY: array of Double;
1522     const KnownX: array of Double) : Double;
1523     begin
1524     if (High(KnownY) <> High(KnownX)) then
1525     RaiseStatError(stscStatBadCount);
1526     Result := RSquared16(KnownY, KnownX, High(KnownY)+1);
1527     end;
1528    
1529     function RSquared16(const KnownY; const KnownX; NData : Integer) : Double;
1530     var
1531     LF : TStLinEst;
1532     begin
1533     LinEst16(KnownY, KnownX, NData, LF, true);
1534     Result := LF.R2;
1535     end;
1536    
1537     function Slope(const KnownY: array of Double;
1538     const KnownX: array of Double) : Double;
1539     begin
1540     if (High(KnownY) <> High(KnownX)) then
1541     RaiseStatError(stscStatBadCount);
1542     Result := Slope16(KnownY, KnownX, High(KnownY)+1);
1543     end;
1544    
1545     function Slope16(const KnownY; const KnownX; NData : Integer) : Double;
1546     var
1547     LF : TStLinEst;
1548     begin
1549     LinEst16(KnownY, KnownX, NData, LF, false);
1550     Result := LF.B1;
1551     end;
1552    
1553     function StandardErrorY(const KnownY: array of Double;
1554     const KnownX: array of Double) : Double;
1555     begin
1556     if (High(KnownY) <> High(KnownX)) then
1557     RaiseStatError(stscStatBadCount);
1558     Result := StandardErrorY16(KnownY, KnownX, High(KnownY)+1);
1559     end;
1560    
1561     function StandardErrorY16(const KnownY; const KnownX;
1562     NData : Integer) : Double;
1563     var
1564     LF : TStLinEst;
1565     begin
1566     LinEst16(KnownY, KnownX, NData, LF, true);
1567     Result := LF.sigma;
1568     end;
1569    
1570     {------------------------------------------------------------------------}
1571    
1572     function BetaCf(a, b, x : Single) : Single;
1573     {-Evaluates continued fraction for incomplete beta function}
1574     const
1575     MAXIT = 100;
1576     EPS = 3.0E-7;
1577     FPMIN = 1.0E-30;
1578     var
1579     m, m2 : Integer;
1580     aa, c, d, del, h, qab, qam, qap : Double;
1581     begin
1582     qab := a+b;
1583     qap := a+1.0;
1584     qam := a-1.0;
1585     c := 1.0;
1586     d := 1.0-qab*x/qap;
1587     if (abs(d) < FPMIN) then
1588     d := FPMIN;
1589     d := 1.0/d;
1590     h := d;
1591     for m := 1 to MAXIT do begin
1592     m2 := 2*m;
1593     aa := m*(b-m)*x/((qam+m2)*(a+m2));
1594     d := 1.0+aa*d;
1595     if (abs(d) < FPMIN) then
1596     d := FPMIN;
1597     c := 1.0+aa/c;
1598     if (abs(c) < FPMIN) then
1599     c := FPMIN;
1600     d := 1.0/d;
1601     h := h*d*c;
1602     aa := -(a+m)*(qab+m)*x/((a+m2)*(qap+m2));
1603    
1604     d := 1.0+aa*d;
1605     if (abs(d) < FPMIN) then
1606     d := FPMIN;
1607     c := 1.0+aa/c;
1608     if (abs(c) < FPMIN) then
1609     c := FPMIN;
1610     d := 1.0/d;
1611     del := d*c;
1612     h := h*del;
1613    
1614     {check for convergence}
1615     if (abs(del-1.0) < EPS) then
1616     break;
1617     if m = MAXIT then
1618     RaiseStatError(stscStatNoConverge);
1619     end;
1620     Result := h;
1621     end;
1622    
1623     function BetaDist(X, Alpha, Beta, A, B : Single) : Single;
1624     var
1625     bt : Double;
1626     begin
1627     if (X < A) or (X > B) or (A = B) or (Alpha <= 0.0) or (Beta <= 0.0) then
1628     RaiseStatError(stscStatBadParam);
1629    
1630     {normalize X}
1631     X := (X-A)/(B-A);
1632    
1633     {compute factors in front of continued fraction expansion}
1634     if (X = 0.0) or (X = 1.0) then
1635     bt := 0.0
1636     else
1637     bt := exp(GammaLn(Alpha+Beta)-GammaLn(Alpha)-GammaLn(Beta)+
1638     Alpha*ln(X)+Beta*ln(1.0-X));
1639    
1640     {use symmetry relationship to make continued fraction converge quickly}
1641     if (X < (Alpha+1.0)/(Alpha+Beta+2.0)) then
1642     Result := bt*BetaCf(Alpha, Beta, X)/Alpha
1643     else
1644     Result := 1.0-bt*BetaCf(Beta, Alpha, 1.0-X)/Beta;
1645     end;
1646    
1647     function Sign(a, b : Double) : Double;
1648     {-Returns abs(a) if b >= 0.0, else -abs(a)}
1649     begin
1650     if (b >= 0.0) then
1651     Result := abs(a)
1652     else
1653     Result := -abs(a);
1654     end;
1655    
1656     function BetaInv(Probability, Alpha, Beta, A, B : Single) : Single;
1657     const
1658     MAXIT = 100;
1659     UNUSED = -1.11e30;
1660     XACC = 3e-7;
1661     var
1662     j : Integer;
1663     ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew, dsign : Double;
1664     begin
1665     if (Probability < 0.0) or (Probability > 1.0) or
1666     (A = B) or (Alpha <= 0.0) or (Beta <= 0.0) then
1667     RaiseStatError(stscStatBadParam);
1668    
1669     if (Probability = 0.0) then
1670     Result := A
1671     else if (Probability = 1.0) then
1672     Result := B
1673     else begin
1674     {Ridder's method of finding the root of BetaDist = Probability}
1675     fl := -Probability; {BetaDist(A, Alpha, Beta, A, B)-Probability}
1676     fh := 1.0-Probability; {BetaDist(B, Alpha, Beta, A, B)-Probability}
1677     xl := A;
1678     xh := B;
1679     ans := UNUSED;
1680    
1681     for j := 1 to MAXIT do begin
1682     xm := 0.5*(xl+xh);
1683     fm := BetaDist(xm, Alpha, Beta, A, B)-Probability;
1684     s := sqrt(fm*fm-fl*fh);
1685     if (s = 0.0) then begin
1686     Result := ans;
1687     exit;
1688     end;
1689     if (fl >= fh) then
1690     dsign := 1.0
1691     else
1692     dsign := -1.0;
1693     xnew := xm+(xm-xl)*(dsign*fm/s);
1694     if (abs(xnew-ans) <= XACC) then begin
1695     Result := ans;
1696     exit;
1697     end;
1698     ans := xnew;
1699    
1700     fnew := BetaDist(ans, Alpha, Beta, A, B)-Probability;
1701     if (fnew = 0.0) then begin
1702     Result := ans;
1703     exit;
1704     end;
1705    
1706     {keep root bracketed on next iteration}
1707     if (Sign(fm, fnew) <> fm) then begin
1708     xl := xm;
1709     fl := fm;
1710     xh := ans;
1711     fh := fnew;
1712     end else if (Sign(fl, fnew) <> fl) then begin
1713     xh := ans;
1714     fh := fnew;
1715     end else if (Sign(fh, fnew) <> fh) then begin
1716     xl := ans;
1717     fl := fnew;
1718     end else
1719     {shouldn't get here}
1720     RaiseStatError(stscStatNoConverge);
1721    
1722     if (abs(xh-xl) <= XACC) then begin
1723     Result := ans;
1724     exit;
1725     end;
1726     end;
1727     BetaInv := A; {avoid compiler warning}
1728     RaiseStatError(stscStatNoConverge);
1729     end;
1730     end;
1731    
1732     function BinomDistPmf(N, K : Integer; p : Extended) : Double;
1733     {-Returns the Probability mass function of the binomial distribution}
1734     begin
1735     Result := Combinations(N, K)*IntPower(p, K)*IntPower(1.0-p, N-K);
1736     end;
1737    
1738     function BinomDist(NumberS, Trials : Integer; ProbabilityS : Single;
1739     Cumulative : Boolean) : Single;
1740     begin
1741     if (Trials < 0) or (NumberS < 0) or (NumberS > Trials) or
1742     (ProbabilityS < 0.0) or (ProbabilityS > 1.0) then
1743     RaiseStatError(stscStatBadParam);
1744    
1745     if (Cumulative) then
1746     Result := 1.0+BinomDistPmf(Trials, NumberS, ProbabilityS)-
1747     BetaDist(ProbabilityS, NumberS, Trials-NumberS+1, 0.0, 1.0)
1748     else
1749     Result := BinomDistPmf(Trials, NumberS, ProbabilityS);
1750     end;
1751    
1752     function CritBinom(Trials : Integer; ProbabilityS, Alpha : Single) : Integer;
1753     var
1754     s : Integer;
1755     B : Double;
1756     begin
1757     if (Trials < 0) or (ProbabilityS < 0.0) or (ProbabilityS > 1.0) or
1758     (Alpha < 0.0) or (Alpha > 1.0) then
1759     RaiseStatError(stscStatBadParam);
1760    
1761     B := 0.0;
1762     for s := 0 to Trials do begin
1763     B := B+BinomDistPmf(Trials, s, ProbabilityS);
1764     if (B >= Alpha) then begin
1765     Result := s;
1766     exit;
1767     end;
1768     end;
1769     {in case of roundoff problems}
1770     Result := Trials;
1771     end;
1772    
1773     function GammSer(a, x : Single) : Single;
1774     {-Returns the series computation for GammP}
1775     const
1776     MAXIT = 100;
1777     EPS = 3.0E-7;
1778     var
1779     N : Integer;
1780     sum, del, ap : Double;
1781     begin
1782     Result := 0.0;
1783     if (x > 0.0) then begin
1784     {x shouldn't be < 0.0, tested by caller}
1785     ap := a;
1786     sum := 1.0/a;
1787     del := sum;
1788     for N := 1 to MAXIT do begin
1789     ap := ap+1;
1790     del := del*x/ap;
1791     sum := sum+del;
1792     if (abs(del) < abs(sum)*EPS) then begin
1793     Result := sum*exp(-X+a*ln(X)-GammaLn(a));
1794     exit;
1795     end;
1796     end;
1797     RaiseStatError(stscStatNoConverge);
1798     end;
1799     end;
1800    
1801     function GammCf(a, x : Single) : Single;
1802     {-Returns the continued fraction computation for GammP}
1803     const
1804     MAXIT = 100;
1805     EPS = 3.0e-7;
1806     FPMIN = 1.0e-30;
1807     var
1808     i : Integer;
1809     an, b, c, d, del, h : Double;
1810     begin
1811     b := x+1.0-a;
1812     c := 1.0/FPMIN;
1813     d := 1.0/b;
1814     h := d;
1815     for i := 1 to MAXIT do begin
1816     an := -i*(i-a);
1817     b := b+2.0;
1818     d := an*d+b;
1819     if (abs(d) < FPMIN) then
1820     d := FPMIN;
1821     c := b+an/c;
1822     if (abs(c) < FPMIN) then
1823     c := FPMIN;
1824     d := 1.0/d;
1825     del := d*c;
1826     h := h*del;
1827     if (abs(del-1.0) < EPS) then
1828     break;
1829     if i = MAXIT then
1830     RaiseStatError(stscStatNoConverge);
1831     end;
1832     Result := h*exp(-x+a*ln(x)-GammaLn(a));
1833     end;
1834    
1835     function GammP(a, x : Single) : Single;
1836     {-Returns the incomplete gamma function P(a, x)}
1837     begin
1838     if (x < 0.0) or (a <= 0.0) then
1839     RaiseStatError(stscStatBadParam);
1840     if (x < a+1.0) then
1841     {use the series representation}
1842     Result := GammSer(a, x)
1843     else
1844     {use the continued fraction representation}
1845     Result := 1.0-GammCf(a, x);
1846     end;
1847    
1848     function ChiDist(X : Single; DegreesFreedom : Integer) : Single;
1849     begin
1850     if (DegreesFreedom < 1) or (X < 0.0) then
1851     RaiseStatError(stscStatBadParam);
1852     Result := 1.0-GammP(DegreesFreedom/2.0, X/2.0);
1853     end;
1854    
1855     function ChiInv(Probability : Single; DegreesFreedom : Integer) : Single;
1856     const
1857     MAXIT = 100;
1858     UNUSED = -1.11e30;
1859     XACC = 3e-7;
1860     FACTOR = 1.6;
1861     var
1862     j : Integer;
1863     ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew, dsign : Double;
1864     begin
1865     if (Probability < 0.0) or (Probability > 1.0) or (DegreesFreedom < 1) then
1866     RaiseStatError(stscStatBadParam);
1867    
1868     if (Probability = 0.0) then
1869     Result := 0.0
1870     else begin
1871     {bracket the interval}
1872     xl := 0.0;
1873     xh := 100.0;
1874     fl := ChiDist(xl, DegreesFreedom)-Probability;
1875     fh := ChiDist(xh, DegreesFreedom)-Probability;
1876     for j := 1 to MAXIT do begin
1877     if (fl*fh < 0.0) then
1878     {bracketed the root}
1879     break;
1880     if (abs(fl) < abs(fh)) then begin
1881     xl := xl+FACTOR*(xl-xh);
1882     fl := ChiDist(xl, DegreesFreedom)-Probability;
1883     end else begin
1884     xh := xh+FACTOR*(xh-xl);
1885     fh := ChiDist(xh, DegreesFreedom)-Probability;
1886     end;
1887     end;
1888     if (fl*fh >= 0.0) then
1889     {couldn't bracket it, means Probability too close to 1.0}
1890     RaiseStatError(stscStatNoConverge);
1891    
1892     {Ridder's method of finding the root of ChiDist = Probability}
1893     ans := UNUSED;
1894    
1895     for j := 1 to MAXIT do begin
1896     xm := 0.5*(xl+xh);
1897     fm := ChiDist(xm, DegreesFreedom)-Probability;
1898     s := sqrt(fm*fm-fl*fh);
1899     if (s = 0.0) then begin
1900     Result := ans;
1901     exit;
1902     end;
1903     if (fl >= fh) then
1904     dsign := 1.0
1905     else
1906     dsign := -1.0;
1907     xnew := xm+(xm-xl)*(dsign*fm/s);
1908     if (abs(xnew-ans) <= XACC) then begin
1909     Result := ans;
1910     exit;
1911     end;
1912     ans := xnew;
1913    
1914     fnew := ChiDist(ans, DegreesFreedom)-Probability;
1915     if (fnew = 0.0) then begin
1916     Result := ans;
1917     exit;
1918     end;
1919    
1920     {keep root bracketed on next iteration}
1921     if (Sign(fm, fnew) <> fm) then begin
1922     xl := xm;
1923     fl := fm;
1924     xh := ans;
1925     fh := fnew;
1926     end else if (Sign(fl, fnew) <> fl) then begin
1927     xh := ans;
1928     fh := fnew;
1929     end else if (Sign(fh, fnew) <> fh) then begin
1930     xl := ans;
1931     fl := fnew;
1932     end else
1933     {shouldn't get here}
1934     RaiseStatError(stscStatNoConverge);
1935    
1936     if (abs(xh-xl) <= XACC) then begin
1937     Result := ans;
1938     exit;
1939     end;
1940     end;
1941     Result := 0.0; {avoid compiler warning}
1942     RaiseStatError(stscStatNoConverge);
1943     end;
1944     end;
1945    
1946     function ExponDist(X, Lambda : Single; Cumulative : Boolean) : Single;
1947     begin
1948     if (X < 0.0) or (Lambda <= 0.0) then
1949     RaiseStatError(stscStatBadParam);
1950    
1951     if (Cumulative) then
1952     Result := 1.0-exp(-Lambda*X)
1953     else
1954     Result := Lambda*exp(-Lambda*X);
1955     end;
1956    
1957     function FDist(X : Single;
1958     DegreesFreedom1, DegreesFreedom2 : Integer) : Single;
1959     begin
1960     if (X < 0) or (DegreesFreedom1 < 1) or (DegreesFreedom2 < 1) then
1961     RaiseStatError(stscStatBadParam);
1962    
1963     Result := BetaDist(DegreesFreedom2/(DegreesFreedom2+DegreesFreedom1*X),
1964     DegreesFreedom2/2.0, DegreesFreedom1/2.0, 0.0, 1.0);
1965     end;
1966    
1967     function FInv(Probability : Single;
1968     DegreesFreedom1, DegreesFreedom2 : Integer) : Single;
1969     const
1970     MAXIT = 100;
1971     UNUSED = -1.11e30;
1972     XACC = 3e-7;
1973     FACTOR = 1.6;
1974     var
1975     j : Integer;
1976     ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew, dsign : Double;
1977     begin
1978     if (Probability < 0.0) or (Probability > 1.0) or
1979     (DegreesFreedom1 < 1) or (DegreesFreedom2 < 1) then
1980     RaiseStatError(stscStatBadParam);
1981    
1982     if (Probability = 1.0) then
1983     Result := 0.0
1984     else begin
1985     {bracket the interval}
1986     xl := 0.0;
1987     xh := 100.0;
1988     fl := FDist(xl, DegreesFreedom1, DegreesFreedom2)-Probability;
1989     fh := FDist(xh, DegreesFreedom1, DegreesFreedom2)-Probability;
1990     for j := 1 to MAXIT do begin
1991     if (fl*fh < 0.0) then
1992     {bracketed the root}
1993     break;
1994     if (abs(fl) < abs(fh)) then begin
1995     xl := xl+FACTOR*(xl-xh);
1996     fl := FDist(xl, DegreesFreedom1, DegreesFreedom2)-Probability;
1997     end else begin
1998     xh := xh+FACTOR*(xh-xl);
1999     fh := FDist(xh, DegreesFreedom1, DegreesFreedom2)-Probability;
2000     end;
2001     end;
2002     if (fl*fh >= 0.0) then
2003     {couldn't bracket it, means Probability too close to 0.0}
2004     RaiseStatError(stscStatNoConverge);
2005    
2006     {Ridder's method of finding the root of FDist = Probability}
2007     ans := UNUSED;
2008    
2009     for j := 1 to MAXIT do begin
2010     xm := 0.5*(xl+xh);
2011     fm := FDist(xm, DegreesFreedom1, DegreesFreedom2)-Probability;
2012     s := sqrt(fm*fm-fl*fh);
2013     if (s = 0.0) then begin
2014     Result := ans;
2015     exit;
2016     end;
2017     if (fl >= fh) then
2018     dsign := 1.0
2019     else
2020     dsign := -1.0;
2021     xnew := xm+(xm-xl)*(dsign*fm/s);
2022     if (abs(xnew-ans) <= XACC) then begin
2023     Result := ans;
2024     exit;
2025     end;
2026     ans := xnew;
2027    
2028     fnew := FDist(ans, DegreesFreedom1, DegreesFreedom2)-Probability;
2029     if (fnew = 0.0) then begin
2030     Result := ans;
2031     exit;
2032     end;
2033    
2034     {keep root bracketed on next iteration}
2035     if (Sign(fm, fnew) <> fm) then begin
2036     xl := xm;
2037     fl := fm;
2038     xh := ans;
2039     fh := fnew;
2040     end else if (Sign(fl, fnew) <> fl) then begin
2041     xh := ans;
2042     fh := fnew;
2043     end else if (Sign(fh, fnew) <> fh) then begin
2044     xl := ans;
2045     fl := fnew;
2046     end else
2047     {shouldn't get here}
2048     RaiseStatError(stscStatNoConverge);
2049    
2050     if (abs(xh-xl) <= XACC) then begin
2051     Result := ans;
2052     exit;
2053     end;
2054     end;
2055     Result := 0.0; {avoid compiler warning}
2056     RaiseStatError(stscStatNoConverge);
2057     end;
2058     end;
2059    
2060     function LogNormDist(X, Mean, StandardDev : Single) : Single;
2061     begin
2062     if (X <= 0.0) or (StandardDev <= 0) then
2063     RaiseStatError(stscStatBadParam);
2064     Result := NormSDist((ln(X)-Mean)/StandardDev);
2065     end;
2066    
2067     function LogInv(Probability, Mean, StandardDev : Single) : Single;
2068     begin
2069     if (Probability < 0.0) or (Probability > 1.0) or (StandardDev <= 0) then
2070     RaiseStatError(stscStatBadParam);
2071     Result := exp(Mean+StandardDev*NormSInv(Probability));
2072     end;
2073    
2074     function NormDist(X, Mean, StandardDev : Single;
2075     Cumulative : Boolean) : Single;
2076     var
2077     Z : Extended;
2078     begin
2079     if (StandardDev <= 0) then
2080     RaiseStatError(stscStatBadParam);
2081     Z := (X-Mean)/StandardDev;
2082     if (Cumulative) then
2083     Result := NormSDist(Z)
2084     else
2085     Result := exp(-Z*Z/2.0)/(StandardDev*sqrt2pi);
2086     end;
2087    
2088     function NormInv(Probability, Mean, StandardDev : Single) : Single;
2089     begin
2090     if (Probability < 0.0) or (Probability > 1.0) or (StandardDev <= 0) then
2091     RaiseStatError(stscStatBadParam);
2092     Result := Mean+StandardDev*NormSInv(Probability);
2093     end;
2094    
2095     function Erfc(X : Single) : Single;
2096     var
2097     t, z, ans : Double;
2098     begin
2099     z := abs(X);
2100     t := 1.0/(1.0+0.5*z);
2101     ans := t*exp(-z*z-1.26551223+t*(1.00002368+t*(0.37409196+t*(0.09678418+
2102     t*(-0.18628806+t*(0.27886807+t*(-1.13520398+t*(1.48851587+
2103     t*(-0.82215223+t*0.17087277)))))))));
2104     if (X >= 0.0) then
2105     Result := ans
2106     else
2107     Result := 2.0-ans;
2108     end;
2109    
2110     function NormSDist(Z : Single) : Single;
2111     const
2112     sqrt2 = 1.41421356237310;
2113     begin
2114     Result := 1.0-0.5*Erfc(Z/sqrt2);
2115     end;
2116    
2117     function NormSInv(Probability : Single) : Single;
2118     const
2119     MAXIT = 100;
2120     UNUSED = -1.11e30;
2121     XACC = 3e-7;
2122     FACTOR = 1.6;
2123     var
2124     j : Integer;
2125     ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew, dsign : Double;
2126     begin
2127     if (Probability < 0.0) or (Probability > 1.0) then
2128     RaiseStatError(stscStatBadParam);
2129     Result := 0.0;
2130    
2131     {bracket the interval}
2132     xl := -2.0;
2133     xh := +2.0;
2134     fl := NormSDist(xl)-Probability;
2135     fh := NormSDist(xh)-Probability;
2136     for j := 1 to MAXIT do begin
2137     if (fl*fh < 0.0) then
2138     {bracketed the root}
2139     break;
2140     if (abs(fl) < abs(fh)) then begin
2141     xl := xl+FACTOR*(xl-xh);
2142     fl := NormSDist(xl)-Probability;
2143     end else begin
2144     xh := xh+FACTOR*(xh-xl);
2145     fh := NormSDist(xh)-Probability;
2146     end;
2147     end;
2148     if (fl*fh >= 0.0) then
2149     {couldn't bracket it, means Probability too close to 0.0 or 1.0}
2150     RaiseStatError(stscStatNoConverge);
2151    
2152     {Ridder's method of finding the root of NormSDist = Probability}
2153     ans := UNUSED;
2154    
2155     for j := 1 to MAXIT do begin
2156     xm := 0.5*(xl+xh);
2157     fm := NormSDist(xm)-Probability;
2158     s := sqrt(fm*fm-fl*fh);
2159     if (s = 0.0) then begin
2160     Result := ans;
2161     exit;
2162     end;
2163     if (fl >= fh) then
2164     dsign := 1.0
2165     else
2166     dsign := -1.0;
2167     xnew := xm+(xm-xl)*(dsign*fm/s);
2168     if (abs(xnew-ans) <= XACC) then begin
2169     Result := ans;
2170     exit;
2171     end;
2172     ans := xnew;
2173    
2174     fnew := NormSDist(ans)-Probability;
2175     if (fnew = 0.0) then begin
2176     Result := ans;
2177     exit;
2178     end;
2179    
2180     {keep root bracketed on next iteration}
2181     if (Sign(fm, fnew) <> fm) then begin
2182     xl := xm;
2183     fl := fm;
2184     xh := ans;
2185     fh := fnew;
2186     end else if (Sign(fl, fnew) <> fl) then begin
2187     xh := ans;
2188     fh := fnew;
2189     end else if (Sign(fh, fnew) <> fh) then begin
2190     xl := ans;
2191     fl := fnew;
2192     end else
2193     {shouldn't get here}
2194     RaiseStatError(stscStatNoConverge);
2195    
2196     if (abs(xh-xl) <= XACC) then begin
2197     Result := ans;
2198     exit;
2199     end;
2200     end;
2201     RaiseStatError(stscStatNoConverge);
2202     end;
2203    
2204     function Poisson(X : Integer; Mean : Single; Cumulative : Boolean) : Single;
2205     begin
2206     if (X < 0) or (Mean <= 0.0) then
2207     RaiseStatError(stscStatBadParam);
2208     if (Cumulative) then
2209     Result := 1.0-GammP(X+1.0, Mean)
2210     else
2211     Result := IntPower(Mean, X)*exp(-Mean)/Factorial(X);
2212     end;
2213    
2214     function TDist(X : Single; DegreesFreedom : Integer;
2215     TwoTails : Boolean) : Single;
2216     var
2217     a : Double;
2218     begin
2219     if (DegreesFreedom < 1) then
2220     RaiseStatError(stscStatBadParam);
2221    
2222     a := BetaDist(DegreesFreedom/(DegreesFreedom+X*X), DegreesFreedom/2.0,
2223     0.5, 0.0, 1.0);
2224     if TwoTails then
2225     Result := a
2226     else
2227     Result := 0.5*a;
2228     end;
2229    
2230     function TInv(Probability : Single; DegreesFreedom : Integer) : Single;
2231     const
2232     MAXIT = 100;
2233     UNUSED = -1.11e30;
2234     XACC = 3e-7;
2235     FACTOR = 1.6;
2236     var
2237     j : Integer;
2238     ans, fh, fl, fm, fnew, s, xh, xl, xm, xnew, dsign : Double;
2239     begin
2240     if (Probability < 0.0) or (Probability > 1.0) or (DegreesFreedom < 1) then
2241     RaiseStatError(stscStatBadParam);
2242    
2243     Result := 0.0;
2244     if (Probability = 1.0) then
2245     exit;
2246    
2247     {bracket the interval}
2248     xl := 0.0;
2249     xh := +2.0;
2250     fl := TDist(xl, DegreesFreedom, true)-Probability;
2251     fh := TDist(xh, DegreesFreedom, true)-Probability;
2252     for j := 1 to MAXIT do begin
2253     if (fl*fh < 0.0) then
2254     {bracketed the root}
2255     break;
2256     if (abs(fl) < abs(fh)) then begin
2257     xl := xl+FACTOR*(xl-xh);
2258     fl := TDist(xl, DegreesFreedom, true)-Probability;
2259     end else begin
2260     xh := xh+FACTOR*(xh-xl);
2261     fh := TDist(xh, DegreesFreedom, true)-Probability;
2262     end;
2263     end;
2264     if (fl*fh >= 0.0) then
2265     {couldn't bracket it, means Probability too close to 1.0}
2266     RaiseStatError(stscStatNoConverge);
2267    
2268     {Ridder's method of finding the root of TDist = Probability}
2269     ans := UNUSED;
2270    
2271     for j := 1 to MAXIT do begin
2272     xm := 0.5*(xl+xh);
2273     fm := TDist(xm, DegreesFreedom, true)-Probability;
2274     s := sqrt(fm*fm-fl*fh);
2275     if (s = 0.0) then begin
2276     Result := ans;
2277     exit;
2278     end;
2279     if (fl >= fh) then
2280     dsign := 1.0
2281     else
2282     dsign := -1.0;
2283     xnew := xm+(xm-xl)*(dsign*fm/s);
2284     if (abs(xnew-ans) <= XACC) then begin
2285     Result := ans;
2286     exit;
2287     end;
2288     ans := xnew;
2289    
2290     fnew := TDist(ans, DegreesFreedom, true)-Probability;
2291     if (fnew = 0.0) then begin
2292     Result := ans;
2293     exit;
2294     end;
2295    
2296     {keep root bracketed on next iteration}
2297     if (Sign(fm, fnew) <> fm) then begin
2298     xl := xm;
2299     fl := fm;
2300     xh := ans;
2301     fh := fnew;
2302     end else if (Sign(fl, fnew) <> fl) then begin
2303     xh := ans;
2304     fh := fnew;
2305     end else if (Sign(fh, fnew) <> fh) then begin
2306     xl := ans;
2307     fl := fnew;
2308     end else
2309     {shouldn't get here}
2310     RaiseStatError(stscStatNoConverge);
2311    
2312     if (abs(xh-xl) <= XACC) then begin
2313     Result := ans;
2314     exit;
2315     end;
2316     end;
2317     RaiseStatError(stscStatNoConverge);
2318     end;
2319    
2320     procedure Initialize;
2321     {-Fully initializes factorial lookup tables}
2322     var
2323     i : Integer;
2324     begin
2325     FactA[2] := 2.0;
2326     for i := 3 to MFactA do
2327     FactA[i] := i*FactA[i-1];
2328     for i := 2 to MFactLna do
2329     FactLnA[i] := GammaLn(i+1.0);
2330     end;
2331    
2332     initialization
2333     Initialize;
2334     end.

  ViewVC Help
Powered by ViewVC 1.1.20