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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2671 - (show annotations) (download)
Tue Aug 25 18:15:15 2015 UTC (8 years, 9 months ago) by torben
File size: 69628 byte(s)
Added tpsystools component
1 // 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