You've already forked lazarus-ccr
LazStats: Further refactoring of ResistanceLineUnit. Some rearrangement of units to make MathUnit only dependent on Globals (for easier testing).
git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7756 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
@ -67,7 +67,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
TATypes,
|
TATypes,
|
||||||
Math, Utils;
|
Math, Utils, MathUnit;
|
||||||
|
|
||||||
|
|
||||||
{ TMultXvsYFrm }
|
{ TMultXvsYFrm }
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Use file "Sickness.laz" for testing
|
// Use file "Sickness.laz" for testing
|
||||||
|
|
||||||
// to do Not sure about the "red" slope line...
|
// to do Not sure about the "red" slope line...
|
||||||
// to do: There are also two positions where a negative intercept is made positive. Why? Correct?
|
// to do: There are also two code positions where a negative intercept is made positive. Why? Correct?
|
||||||
|
|
||||||
unit ResistanceLineUnit;
|
unit ResistanceLineUnit;
|
||||||
|
|
||||||
@ -12,9 +12,8 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
|
Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
|
||||||
StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls,
|
StdCtrls, ExtCtrls, Buttons, Printers, ComCtrls,
|
||||||
MainUnit, Globals, FunctionsLib, OutputUnit, DataProcs, DictionaryUnit,
|
MainUnit, Globals, DataProcs, DictionaryUnit,
|
||||||
//BlankFrmUnit,
|
MathUnit, BasicStatsReportAndChartFormUnit;
|
||||||
BasicStatsReportAndChartFormUnit;
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -55,8 +54,8 @@ type
|
|||||||
private
|
private
|
||||||
procedure PlotMedians(const XMedians, YMedians: DblDyneVec;
|
procedure PlotMedians(const XMedians, YMedians: DblDyneVec;
|
||||||
ASlope, AIntercept: Double);
|
ASlope, AIntercept: Double);
|
||||||
procedure PlotXY(const XPoints, YPoints, UpConf, LowConf: DblDyneVec;
|
procedure PlotXY(const XPoints, YPoints: DblDyneVec;
|
||||||
XMean, YMean, R, ASlope, AIntercept: Double);
|
ARegressionResults: TBivariateRegressionResults);
|
||||||
|
|
||||||
procedure ResidualsToGrid(xCol, yCol: Integer;
|
procedure ResidualsToGrid(xCol, yCol: Integer;
|
||||||
const AColNoSelected: IntDyneVec; Slope, Intercept: Double);
|
const AColNoSelected: IntDyneVec; Slope, Intercept: Double);
|
||||||
@ -68,8 +67,7 @@ type
|
|||||||
const XMedians, YMedians: DblDyneVec; const GrpSize: IntDyneVec;
|
const XMedians, YMedians: DblDyneVec; const GrpSize: IntDyneVec;
|
||||||
Slope1, Slope2, Slope, Intercept: Double);
|
Slope1, Slope2, Slope, Intercept: Double);
|
||||||
procedure WriteXYReport(AReport: TStrings; AFileName: String;
|
procedure WriteXYReport(AReport: TStrings; AFileName: String;
|
||||||
xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, R, Slope, Intercept, SEPred: double;
|
const ARegressionResults: TBivariateRegressionResults);
|
||||||
N: Integer);
|
|
||||||
|
|
||||||
protected
|
protected
|
||||||
procedure AdjustConstraints; override;
|
procedure AdjustConstraints; override;
|
||||||
@ -91,7 +89,7 @@ implementation
|
|||||||
uses
|
uses
|
||||||
Math, Grids,
|
Math, Grids,
|
||||||
TATypes, TAChartUtils, TAChartAxisUtils, TALegend, TASources, TACustomSeries,
|
TATypes, TAChartUtils, TAChartAxisUtils, TALegend, TASources, TACustomSeries,
|
||||||
ChartFrameUnit, Utils, MathUnit, GridProcs;
|
ChartFrameUnit, Utils, GridProcs;
|
||||||
|
|
||||||
{ TResistanceLineForm }
|
{ TResistanceLineForm }
|
||||||
|
|
||||||
@ -142,15 +140,13 @@ var
|
|||||||
xMedians: DblDyneVec = nil;
|
xMedians: DblDyneVec = nil;
|
||||||
yMedians: DblDyneVec = nil;
|
yMedians: DblDyneVec = nil;
|
||||||
colNoSelected : IntDyneVec = nil;
|
colNoSelected : IntDyneVec = nil;
|
||||||
upConf: DblDyneVec = nil;
|
|
||||||
lowConf: DblDyneVec = nil;
|
|
||||||
grpSize: IntDyneVec = nil;
|
grpSize: IntDyneVec = nil;
|
||||||
xCol, yCol: Integer;
|
xCol, yCol: Integer;
|
||||||
i, N, DF: integer;
|
regressionRes: TBivariateRegressionResults;
|
||||||
xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, SXX, SXY, SYY, t: Double;
|
N: Integer;
|
||||||
confBand, yPred: double;
|
confBand: Double;
|
||||||
R, SEPred, interceptFit, slopeFit, slope1, slope2, slopeRL, seData: double;
|
slope1, slope2, slopeRL: Double;
|
||||||
c, c1, c2, c3 : double; // constants obtained from control points
|
c1, c2, c3, c: Double;
|
||||||
lReport: TStrings;
|
lReport: TStrings;
|
||||||
dataGrid: TStringGrid;
|
dataGrid: TStringGrid;
|
||||||
begin
|
begin
|
||||||
@ -178,9 +174,9 @@ begin
|
|||||||
xyPoints[0] := CollectValues(dataGrid, xCol, colNoSelected);
|
xyPoints[0] := CollectValues(dataGrid, xCol, colNoSelected);
|
||||||
xyPoints[1] := CollectValues(dataGrid, ycol, colNoSelected);
|
xyPoints[1] := CollectValues(dataGrid, ycol, colNoSelected);
|
||||||
N := Length(xyPoints[0]);
|
N := Length(xyPoints[0]);
|
||||||
if N = 0 then
|
if N < 3 then
|
||||||
begin
|
begin
|
||||||
ErrorMsg('No data points.');
|
ErrorMsg('At least three data points required.');
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
if N <> Length(xyPoints[1]) then
|
if N <> Length(xyPoints[1]) then
|
||||||
@ -192,36 +188,9 @@ begin
|
|||||||
// Sort on the x values
|
// Sort on the x values
|
||||||
SortOnX(xyPoints[0], xyPoints[1]);
|
SortOnX(xyPoints[0], xyPoints[1]);
|
||||||
|
|
||||||
// Calculate means, variances, stddevs
|
// Calculate bivariate regression
|
||||||
Calc_MeanVarStdDevSS(xyPoints[0], xMean, xVariance, xStdDev, SXX);
|
confBand := StrToFloat(ConfEdit.Text) / 100;
|
||||||
Calc_MeanVarStdDevSS(xyPoints[1], yMean, yVariance, yStdDev, SYY);
|
Calc_BivariateRegression(xyPoints[0], xyPoints[1], confBand, regressionRes);
|
||||||
|
|
||||||
// Calculate linear fit of x vs y
|
|
||||||
SXY := 0;
|
|
||||||
for i := 0 to N-1 do
|
|
||||||
SXY := SXY + xyPoints[0, i] * xyPoints[1, i];
|
|
||||||
|
|
||||||
R := (SXY - xMean * yMean * N) / ((N - 1) * xStdDev * yStdDev);
|
|
||||||
sePred := sqrt(1.0 - sqr(R)) * yStdDev * sqrt((N - 1) / (N - 2));
|
|
||||||
slopeFit := R * yStdDev / xStdDev;
|
|
||||||
interceptFit := yMean - slopeFit * xMean;
|
|
||||||
|
|
||||||
// Get upper and lower confidence limits for each x value
|
|
||||||
if ConfChk.Checked then
|
|
||||||
begin
|
|
||||||
SetLength(upConf, N);
|
|
||||||
SetLength(lowConf, N);
|
|
||||||
confBand := StrToFloat(ConfEdit.Text) / 100.0;
|
|
||||||
DF := N - 2;
|
|
||||||
t := InverseT(ConfBand, DF);
|
|
||||||
for i := 0 to N-1 do
|
|
||||||
begin
|
|
||||||
yPred := interceptFit + slopeFit * xyPoints[0, i];
|
|
||||||
seData := sePred * sqrt(1.0 + 1/N + sqr(xyPoints[0, i] - xMean)/SXX);
|
|
||||||
upConf[i] := yPred + t * seData;
|
|
||||||
lowConf[i] := yPred - t * seData;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// Do the resistant line analysis
|
// Do the resistant line analysis
|
||||||
ResistantLineAnalysis(xyPoints, xMedians, yMedians, grpSize);
|
ResistantLineAnalysis(xyPoints, xMedians, yMedians, grpSize);
|
||||||
@ -240,6 +209,7 @@ begin
|
|||||||
if GridChk.Checked then
|
if GridChk.Checked then
|
||||||
ResidualsToGrid(xCol, yCol, colNoSelected, slopeRL, c);
|
ResidualsToGrid(xCol, yCol, colNoSelected, slopeRL, c);
|
||||||
|
|
||||||
|
// Write results to report in ReportFrame
|
||||||
lReport := TStringList.Create;
|
lReport := TStringList.Create;
|
||||||
try
|
try
|
||||||
WriteMedianReport(lReport,
|
WriteMedianReport(lReport,
|
||||||
@ -250,9 +220,7 @@ begin
|
|||||||
if DescChk.Checked then
|
if DescChk.Checked then
|
||||||
WriteXYReport(lReport,
|
WriteXYReport(lReport,
|
||||||
OS3MainFrm.FileNameEdit.Text,
|
OS3MainFrm.FileNameEdit.Text,
|
||||||
xMean, yMean, xVariance, yVariance, xStdDev, yStdDev,
|
regressionRes
|
||||||
R, slopeFit, interceptFit, sePred,
|
|
||||||
N
|
|
||||||
);
|
);
|
||||||
|
|
||||||
FReportFrame.DisplayReport(lReport);
|
FReportFrame.DisplayReport(lReport);
|
||||||
@ -260,8 +228,9 @@ begin
|
|||||||
lReport.Free;
|
lReport.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
// Plot results in ChartFrame
|
||||||
if PlotPointsChk.Checked then
|
if PlotPointsChk.Checked then
|
||||||
PlotXY(xyPoints[0], xyPoints[1], upConf, lowConf, xMean, yMean, R, slopeFit, interceptFit);
|
PlotXY(xyPoints[0], xyPoints[1], regressionRes);
|
||||||
|
|
||||||
if PlotMediansChk.Checked then
|
if PlotMediansChk.Checked then
|
||||||
PlotMedians(XMedians, YMedians, slopeRL, c);
|
PlotMedians(XMedians, YMedians, slopeRL, c);
|
||||||
@ -312,14 +281,16 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TResistanceLineForm.PlotXY(const XPoints, YPoints, UpConf, LowConf: DblDyneVec;
|
procedure TResistanceLineForm.PlotXY(const XPoints, YPoints: DblDyneVec;
|
||||||
XMean, YMean, R, ASlope, AIntercept: Double);
|
ARegressionResults: TBivariateRegressionResults);
|
||||||
var
|
var
|
||||||
ser: TChartSeries;
|
ser: TChartSeries;
|
||||||
xPts: DblDyneVec = nil;
|
xPts: DblDyneVec = nil;
|
||||||
yPts: DblDyneVec = nil;
|
yPts: DblDyneVec = nil;
|
||||||
|
conf: DblDyneVec = nil;
|
||||||
rightLabels: TListChartSource;
|
rightLabels: TListChartSource;
|
||||||
topLabels: TListChartSource;
|
topLabels: TListChartSource;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
rightLabels := FChartFrame.Chart.AxisList[2].Marks.Source as TListChartSource;
|
rightLabels := FChartFrame.Chart.AxisList[2].Marks.Source as TListChartSource;
|
||||||
rightLabels.Clear;
|
rightLabels.Clear;
|
||||||
@ -331,12 +302,14 @@ begin
|
|||||||
FChartFrame.Chart.Margins.Right := 4;
|
FChartFrame.Chart.Margins.Right := 4;
|
||||||
|
|
||||||
FChartFrame.SetTitle('X vs Y plot using file '+ OS3MainFrm.FileNameEdit.Text);
|
FChartFrame.SetTitle('X vs Y plot using file '+ OS3MainFrm.FileNameEdit.Text);
|
||||||
FChartFrame.SetFooter(Format('R(X,Y) = %.3f, Slope = %.2f, Intercept = %.2f', [R, ASlope, AIntercept]));
|
with ARegressionResults do
|
||||||
|
FChartFrame.SetFooter(Format('R(X,Y) = %.3f, Slope = %.2f, Intercept = %.2f', [R, Slope, Intercept]));
|
||||||
FChartFrame.SetXTitle(XEdit.Text);
|
FChartFrame.SetXTitle(XEdit.Text);
|
||||||
FChartFrame.SetYTitle(YEdit.Text);
|
FChartFrame.SetYTitle(YEdit.Text);
|
||||||
|
|
||||||
// Draw means
|
// Draw means
|
||||||
if MeansChk.Checked then
|
if MeansChk.Checked then
|
||||||
|
with ARegressionResults do
|
||||||
begin
|
begin
|
||||||
FChartFrame.VertLine(XMean, clGreen, psDashDot, 'Mean ' + XEdit.Text);
|
FChartFrame.VertLine(XMean, clGreen, psDashDot, 'Mean ' + XEdit.Text);
|
||||||
topLabels.Add(XMean, XMean, 'Mean ' + XEdit.Text);
|
topLabels.Add(XMean, XMean, 'Mean ' + XEdit.Text);
|
||||||
@ -351,24 +324,29 @@ begin
|
|||||||
SetLength(xPts, 2);
|
SetLength(xPts, 2);
|
||||||
SetLength(yPts, 2);
|
SetLength(yPts, 2);
|
||||||
xPts[0] := XPoints[0];
|
xPts[0] := XPoints[0];
|
||||||
yPts[0] := AIntercept + XPoints[0] * ASlope;
|
|
||||||
xPts[1] := XPoints[High(XPoints)];
|
xPts[1] := XPoints[High(XPoints)];
|
||||||
yPts[1] := AIntercept + XPoints[High(XPoints)] * ASlope;
|
with ARegressionResults do
|
||||||
|
begin
|
||||||
|
yPts[0] := Intercept + XPoints[0] * Slope;
|
||||||
|
yPts[1] := Intercept + XPoints[High(XPoints)] * Slope;
|
||||||
|
end;
|
||||||
ser := FChartFrame.PlotXY(ptLines, xpts, ypts, nil, nil, 'Regression', clBlack);
|
ser := FChartFrame.PlotXY(ptLines, xpts, ypts, nil, nil, 'Regression', clBlack);
|
||||||
rightLabels.Add(ser.XValue[ser.Count-1], ser.YValue[ser.Count-1], 'Regression');
|
rightLabels.Add(ser.XValue[ser.Count-1], ser.YValue[ser.Count-1], 'Regression');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Draw upper confidence band
|
|
||||||
if ConfChk.Checked then
|
if ConfChk.Checked then
|
||||||
begin
|
begin
|
||||||
ser := FChartFrame.PlotXY(ptLines, XPoints, UpConf, nil, nil, 'Upper confidence band', clRed);
|
// Draw upper confidence band
|
||||||
|
SetLength(conf, ARegressionResults.Count);
|
||||||
|
for i := 0 to ARegressionResults.Count-1 do
|
||||||
|
conf[i] := ARegressionResults.ConfidenceLimits(XPoints[i], true);
|
||||||
|
ser := FChartFrame.PlotXY(ptLines, XPoints, conf, nil, nil, 'Upper confidence band', clRed);
|
||||||
rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'UCL');
|
rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'UCL');
|
||||||
end;
|
|
||||||
|
|
||||||
// Draw lower confidence band
|
// Draw lower confidence band
|
||||||
if ConfChk.Checked then
|
for i := 0 to ARegressionResults.Count-1 do
|
||||||
begin
|
conf[i] := ARegressionResults.ConfidenceLimits(XPoints[i], false);
|
||||||
ser := FChartFrame.PlotXY(ptLines, XPoints, LowConf, nil, nil, 'Lower confidence band', clRed);
|
ser := FChartFrame.PlotXY(ptLines, XPoints, conf, nil, nil, 'Lower confidence band', clRed);
|
||||||
rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'LCL');
|
rightLabels.Add(ser.yValue[ser.Count-1], ser.YValue[ser.Count-1], 'LCL');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -587,8 +565,11 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
procedure TResistanceLineForm.WriteXYReport(AReport: TStrings; AFileName: String;
|
procedure TResistanceLineForm.WriteXYReport(AReport: TStrings; AFileName: String;
|
||||||
|
const ARegressionResults: TBivariateRegressionResults);
|
||||||
|
{
|
||||||
xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, R, slope, intercept, SEPred: double;
|
xMean, yMean, xVariance, yVariance, xStdDev, yStdDev, R, slope, intercept, SEPred: double;
|
||||||
N: Integer);
|
N: Integer);
|
||||||
|
}
|
||||||
begin
|
begin
|
||||||
AReport.Add('');
|
AReport.Add('');
|
||||||
AReport.Add(DIVIDER);
|
AReport.Add(DIVIDER);
|
||||||
@ -599,10 +580,22 @@ begin
|
|||||||
AReport.Add('Variables:');
|
AReport.Add('Variables:');
|
||||||
AReport.Add(' X: ' + XEdit.Text);
|
AReport.Add(' X: ' + XEdit.Text);
|
||||||
AReport.Add(' Y: ' + YEdit.Text);
|
AReport.Add(' Y: ' + YEdit.Text);
|
||||||
// AReport.Add('X = %s, Y = %s from file: %s', [XEdit.Text, YEdit.Text, AFileName]);
|
|
||||||
AReport.Add('');
|
AReport.Add('');
|
||||||
AReport.Add('Variable Mean Variance Std.Dev.');
|
AReport.Add('Variable Mean Variance Std.Dev.');
|
||||||
AReport.Add('---------- -------- -------- --------');
|
AReport.Add('---------- -------- -------- --------');
|
||||||
|
with ARegressionResults do
|
||||||
|
begin
|
||||||
|
AReport.Add('%-10s %8.2f %8.2f %8.2f', [XEdit.Text, XMean, XVariance, XStdDev]);
|
||||||
|
AReport.Add('%-10s %8.2f %8.2f %8.2f', [YEdit.Text, YMean, YVariance, YStdDev]);
|
||||||
|
AReport.Add('');
|
||||||
|
AReport.Add('Correlation: %8.4f', [R]);
|
||||||
|
AReport.Add('Slope: %8.3f', [Slope]);
|
||||||
|
AReport.Add('Intercept: %8.3f', [Intercept]);
|
||||||
|
AReport.Add('Standard Error of Estimate: %8.3f', [StdErrorPredicted]);
|
||||||
|
AReport.Add('Number of good cases: %8d', [Count]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
{
|
||||||
AReport.Add('%-10s %8.2f %8.2f %8.2f', [XEdit.Text, xMean, xVariance, xStdDev]);
|
AReport.Add('%-10s %8.2f %8.2f %8.2f', [XEdit.Text, xMean, xVariance, xStdDev]);
|
||||||
AReport.Add('%-10s %8.2f %8.2f %8.2f', [YEdit.Text, yMean, yVariance, yStdDev]);
|
AReport.Add('%-10s %8.2f %8.2f %8.2f', [YEdit.Text, yMean, yVariance, yStdDev]);
|
||||||
AReport.Add('');
|
AReport.Add('');
|
||||||
@ -611,6 +604,7 @@ begin
|
|||||||
AReport.Add('Intercept: %8.3f', [Intercept]);
|
AReport.Add('Intercept: %8.3f', [Intercept]);
|
||||||
AReport.Add('Standard Error of Estimate: %8.3f', [SEPred]);
|
AReport.Add('Standard Error of Estimate: %8.3f', [SEPred]);
|
||||||
AReport.Add('Number of good cases: %8d', [N]);
|
AReport.Add('Number of good cases: %8d', [N]);
|
||||||
|
}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Math,
|
Math,
|
||||||
Utils;
|
Utils, MathUnit;
|
||||||
|
|
||||||
{ TGradebookFrm }
|
{ TGradebookFrm }
|
||||||
|
|
||||||
|
@ -72,7 +72,7 @@ implementation
|
|||||||
|
|
||||||
uses
|
uses
|
||||||
Math,
|
Math,
|
||||||
Utils, GradebookUnit;
|
Utils, MathUnit, GradebookUnit;
|
||||||
|
|
||||||
{ TGradingFrm }
|
{ TGradingFrm }
|
||||||
|
|
||||||
|
@ -85,7 +85,8 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, Utils;
|
Math,
|
||||||
|
Utils, MathUnit;
|
||||||
|
|
||||||
{ TKMeansFrm }
|
{ TKMeansFrm }
|
||||||
|
|
||||||
|
@ -83,7 +83,8 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, Utils;
|
Math,
|
||||||
|
Utils, MathUnit;
|
||||||
|
|
||||||
{ TMedianPolishForm }
|
{ TMedianPolishForm }
|
||||||
|
|
||||||
|
@ -84,7 +84,8 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, Utils;
|
Math,
|
||||||
|
Utils, MathUnit;
|
||||||
|
|
||||||
{ TPathFrm }
|
{ TPathFrm }
|
||||||
|
|
||||||
|
@ -61,7 +61,8 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, Utils;
|
Math,
|
||||||
|
Utils, MathUnit;
|
||||||
|
|
||||||
{ TSingleLinkFrm }
|
{ TSingleLinkFrm }
|
||||||
|
|
||||||
|
@ -65,7 +65,8 @@ var
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math, Utils;
|
Math,
|
||||||
|
Utils, MathUnit;
|
||||||
|
|
||||||
{ TSensForm }
|
{ TSensForm }
|
||||||
|
|
||||||
|
@ -9,6 +9,15 @@ uses
|
|||||||
ExtCtrls, StdCtrls, Printers, Math,
|
ExtCtrls, StdCtrls, Printers, Math,
|
||||||
Globals;
|
Globals;
|
||||||
|
|
||||||
|
const
|
||||||
|
DATA_COLORS: array[0..10] of TColor = (
|
||||||
|
$A1A45D, $3153C4, $0996E7, $4AE8F6, $A7A2B1,
|
||||||
|
$84A7C9, $51798C, $87CDD8, $536508, $7BD8F3,
|
||||||
|
$846402
|
||||||
|
);
|
||||||
|
// NOTE: This is a duplication of the declaration in ChartUnitFrame and will
|
||||||
|
// become obsolete when the GraphLib unit will be finally replaced by TAChart.
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
|
@ -10,6 +10,18 @@ uses
|
|||||||
TATools,
|
TATools,
|
||||||
Globals, MainDM;
|
Globals, MainDM;
|
||||||
|
|
||||||
|
const
|
||||||
|
DATA_COLORS: array[0..10] of TColor = (
|
||||||
|
$A1A45D, $3153C4, $0996E7, $4AE8F6, $A7A2B1,
|
||||||
|
$84A7C9, $51798C, $87CDD8, $536508, $7BD8F3,
|
||||||
|
$846402
|
||||||
|
);
|
||||||
|
DATA_SYMBOLS: array[0..5] of TSeriesPointerStyle = (
|
||||||
|
psRectangle, psCircle, psDiamond,
|
||||||
|
psDownTriangle, psHexagon, psFullStar
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
type
|
type
|
||||||
TPlotType = (ptLines, ptSymbols, ptLinesAndSymbols, ptBars,
|
TPlotType = (ptLines, ptSymbols, ptLinesAndSymbols, ptBars,
|
||||||
ptArea);
|
ptArea);
|
||||||
|
@ -61,7 +61,7 @@ function StringsToInt(StrCol: integer; var NewCol: integer; Prompt: boolean): bo
|
|||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Utils, MainUnit;
|
Utils, MathUnit, MainUnit;
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Do not call GridProcs.GoodRecord here because this old function may
|
// NOTE: Do not call GridProcs.GoodRecord here because this old function may
|
||||||
|
@ -5,7 +5,7 @@ unit Globals;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, Graphics, TATypes;
|
Classes, SysUtils;
|
||||||
|
|
||||||
type
|
type
|
||||||
IntDyneVec = array of integer;
|
IntDyneVec = array of integer;
|
||||||
@ -75,27 +75,14 @@ const
|
|||||||
DEFAULT_ALPHA_LEVEL = 0.05;
|
DEFAULT_ALPHA_LEVEL = 0.05;
|
||||||
DEFAULT_BETA_LEVEL = 0.20;
|
DEFAULT_BETA_LEVEL = 0.20;
|
||||||
|
|
||||||
{
|
|
||||||
DATA_COLORS: array[0..11] of TColor = (
|
|
||||||
clMaroon, clRed, clBlue, clGreen, clNavy, clTeal,
|
|
||||||
clAqua, clLime, clFuchsia, clGray, clSilver, clOlive
|
|
||||||
);
|
|
||||||
}
|
|
||||||
DATA_COLORS: array[0..10] of TColor = (
|
|
||||||
$A1A45D, $3153C4, $0996E7, $4AE8F6, $A7A2B1, $84A7C9, $51798C, $87CDD8, $536508, $7BD8F3, $846402
|
|
||||||
);
|
|
||||||
DATA_SYMBOLS: array[0..5] of TSeriesPointerStyle = (psRectangle, psCircle, psDiamond,
|
|
||||||
psDownTriangle, psHexagon, psFullStar);
|
|
||||||
|
|
||||||
|
|
||||||
DIVIDER = '===========================================================================';
|
DIVIDER = '===========================================================================';
|
||||||
DIVIDER_SMALL = '---------------------------------------------------------------------------';
|
DIVIDER_SMALL = '---------------------------------------------------------------------------';
|
||||||
DIVIDER_AUTO = '@=';
|
DIVIDER_AUTO = '@=';
|
||||||
DIVIDER_SMALL_AUTO = '@-';
|
DIVIDER_SMALL_AUTO = '@-';
|
||||||
|
|
||||||
GRAPH_BACK_COLOR = clCream;
|
GRAPH_BACK_COLOR = $F0FBFF; // clCream
|
||||||
GRAPH_WALL_COLOR = clGray;
|
GRAPH_WALL_COLOR = $808080; // clGray
|
||||||
GRAPH_FLOOR_COLOR = clLtGray;
|
GRAPH_FLOOR_COLOR = $C0C0C0; // clLtGray
|
||||||
|
|
||||||
TAB_FILE_FILTER = 'Tab field files (*.tab)|*.tab;*.TAB|Text files (*.txt)|*.txt;*.TXT|All files (*.*)|*.*';
|
TAB_FILE_FILTER = 'Tab field files (*.tab)|*.tab;*.TAB|Text files (*.txt)|*.txt;*.TXT|All files (*.*)|*.*';
|
||||||
CSV_FILE_FILTER = 'Comma field files (*.csv)|*.csv;*.CSV|Text files (*.txt)|*.txt;*.TXT|All files (*.*)|*.*';
|
CSV_FILE_FILTER = 'Comma field files (*.csv)|*.csv;*.CSV|Text files (*.txt)|*.txt;*.TXT|All files (*.*)|*.*';
|
||||||
|
@ -3,6 +3,7 @@ unit MathUnit;
|
|||||||
{ extract some math functions from functionslib for easier testing }
|
{ extract some math functions from functionslib for easier testing }
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
{$modeswitch advancedrecords}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
@ -20,15 +21,17 @@ function erfc(x: Double) : Double;
|
|||||||
|
|
||||||
function NormalDist(x: Double): Double;
|
function NormalDist(x: Double): Double;
|
||||||
function NormalDistDensity(x, AMean, AStdDev: Double): Double;
|
function NormalDistDensity(x, AMean, AStdDev: Double): Double;
|
||||||
|
function InverseNormalDist(Probability: Double): Double;
|
||||||
|
|
||||||
function Beta(a, b: Double): Extended;
|
function Beta(a, b: Double): Extended;
|
||||||
function BetaI(a,b,x: Double): Extended;
|
function BetaI(a,b,x: Double): Extended;
|
||||||
|
|
||||||
function GammaLn(x: double): Extended;
|
function GammaLn(x: double): Extended;
|
||||||
|
|
||||||
function tDist(x: Double; DF: Integer; OneSided: Boolean): Double;
|
function tDist(x, DF: Double; OneSided: Boolean): Double;
|
||||||
function tDensity(x: Double; DF: Integer): Double;
|
function tDensity(x, DF: Double): Double;
|
||||||
function ProbT(t, DF1: double): double;
|
function ProbT(t, DF: double): double;
|
||||||
|
function InverseT(Probability, DF: Double): Double;
|
||||||
|
|
||||||
function FDensity(x: Double; DF1, DF2: Integer): Double;
|
function FDensity(x: Double; DF1, DF2: Integer): Double;
|
||||||
function ProbF(F, DF1, DF2: Double): Double;
|
function ProbF(F, DF1, DF2: Double): Double;
|
||||||
@ -44,7 +47,6 @@ function FactorialLn(n: Integer): Double;
|
|||||||
function PoissonPDF(n: integer; a: double): Double;
|
function PoissonPDF(n: integer; a: double): Double;
|
||||||
function PoissonCDF(n: Integer; a: double): Double;
|
function PoissonCDF(n: Integer; a: double): Double;
|
||||||
|
|
||||||
|
|
||||||
procedure Calc_MaxMin(const AData: DblDyneVec; out AMax, AMin: Double);
|
procedure Calc_MaxMin(const AData: DblDyneVec; out AMax, AMin: Double);
|
||||||
procedure Calc_MeanStdDev(const AData: DblDyneVec; out AMean, AStdDev: Double);
|
procedure Calc_MeanStdDev(const AData: DblDyneVec; out AMean, AStdDev: Double);
|
||||||
procedure Calc_MeanVarStdDev(const AData: DblDyneVec; out AMean, AVariance, AStdDev: Double);
|
procedure Calc_MeanVarStdDev(const AData: DblDyneVec; out AMean, AVariance, AStdDev: Double);
|
||||||
@ -53,12 +55,38 @@ procedure Calc_SumSS(const AData: DblDyneVec; out Sum, SS: Double);
|
|||||||
|
|
||||||
function Calc_Median(const AData: DblDyneVec): Double;
|
function Calc_Median(const AData: DblDyneVec): Double;
|
||||||
|
|
||||||
|
type
|
||||||
|
TBivariateRegressionResults = record
|
||||||
|
Slope, Intercept: Double;
|
||||||
|
XMean, YMean: Double;
|
||||||
|
XVariance, YVariance: Double;
|
||||||
|
XStdDev, YStdDev: Double;
|
||||||
|
StdErrorPredicted: Double;
|
||||||
|
R: Double;
|
||||||
|
t: Double;
|
||||||
|
SXX, SXY, SYY: Double;
|
||||||
|
Count, DF: Integer;
|
||||||
|
function ConfidenceLimits(x: Double; Upper: Boolean): Double;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Calc_BivariateRegression(const xData, yData: DblDyneVec; AConfLevel: Double;
|
||||||
|
out AResults: TBivariateRegressionResults);
|
||||||
|
|
||||||
|
procedure Exchange(var a, b: Double); overload;
|
||||||
|
procedure Exchange(var a, b: Integer); overload;
|
||||||
|
procedure Exchange(var a, b: String); overload;
|
||||||
|
|
||||||
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
||||||
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
|
||||||
|
|
||||||
|
procedure QuickSortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil); // not 100% tested...
|
||||||
|
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Math,
|
Math;
|
||||||
Utils;
|
// Utils;
|
||||||
|
|
||||||
// Calculates the error function
|
// Calculates the error function
|
||||||
// /x
|
// /x
|
||||||
@ -160,6 +188,80 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ Obtains the inverse of the normal distribution (z), that is the argument for
|
||||||
|
the NormalDist() function to result in the given probability.
|
||||||
|
|
||||||
|
Probability = 0 ... 1 --> Result = -INF ... +INF
|
||||||
|
|
||||||
|
Algorithm by Peter John Acklam.
|
||||||
|
http://home.online.no/~pjacklam/notes/invnorm/index.html }
|
||||||
|
function InverseNormalDist(Probability: Double): Double;
|
||||||
|
const
|
||||||
|
A: array[1..6] of Double = (
|
||||||
|
-3.969683028665376e+01,
|
||||||
|
+2.209460984245205e+02,
|
||||||
|
-2.759285104469687e+02,
|
||||||
|
+1.383577518672690e+02,
|
||||||
|
-3.066479806614716e+01,
|
||||||
|
+2.506628277459239e+00
|
||||||
|
);
|
||||||
|
B: array[1..5] of Double = (
|
||||||
|
-5.447609879822406e+01,
|
||||||
|
+1.615858368580409e+02,
|
||||||
|
-1.556989798598866e+02,
|
||||||
|
+6.680131188771972e+01,
|
||||||
|
-1.328068155288572e+01
|
||||||
|
);
|
||||||
|
C: array[1..6] of Double = (
|
||||||
|
-7.784894002430293e-03,
|
||||||
|
-3.223964580411365e-01,
|
||||||
|
-2.400758277161838e+00,
|
||||||
|
-2.549732539343734e+00,
|
||||||
|
+4.374664141464968e+00,
|
||||||
|
+2.938163982698783e+00
|
||||||
|
);
|
||||||
|
D: array[1..4] of Double = (
|
||||||
|
+7.784695709041462e-03,
|
||||||
|
+3.224671290700398e-01,
|
||||||
|
+2.445134137142996e+00,
|
||||||
|
+3.754408661907416e+00
|
||||||
|
);
|
||||||
|
// Switching points between regions.
|
||||||
|
P_LOW = 0.02425;
|
||||||
|
P_HIGH = 1 - P_LOW;
|
||||||
|
var
|
||||||
|
q, r: Extended;
|
||||||
|
begin
|
||||||
|
if Probability <= 0 then
|
||||||
|
Result := NegInfinity
|
||||||
|
else
|
||||||
|
if Probability < P_LOW then
|
||||||
|
begin
|
||||||
|
// rational approximation for lower region.
|
||||||
|
q := Sqrt(-2 * ln(Probability));
|
||||||
|
Result :=
|
||||||
|
(((((C[1] * q + C[2]) * q + C[3]) * q + C[4]) * q + C[5]) * q + C[6]) /
|
||||||
|
((((D[1] * q + D[2]) * q + D[3]) * q + D[4]) * q + 1);
|
||||||
|
end else
|
||||||
|
if Probability <= P_HIGH then begin
|
||||||
|
// rational approximation for central region.
|
||||||
|
q := Probability - 0.5 ;
|
||||||
|
r := q * q ;
|
||||||
|
Result :=
|
||||||
|
(((((A[1] * r + A[2]) * r + A[3]) * r + A[4]) * r + A[5]) * r + A[6]) * q /
|
||||||
|
(((((B[1] * r + B[2]) * r + B[3]) * r + B[4]) * r + B[5]) * r + 1);
|
||||||
|
end else
|
||||||
|
if Probability < 1 then begin
|
||||||
|
// rational approximation for upper region.
|
||||||
|
q := Sqrt(-2 * ln(1 - Probability));
|
||||||
|
Result :=
|
||||||
|
-(((((C[1] * q + C[2]) * q + C[3]) * q + C[4]) * q + C[5]) * q + C[6]) /
|
||||||
|
((((D[1] * q + D[2]) * q + D[3]) * q + D[4]) * q + 1);
|
||||||
|
end else
|
||||||
|
Result := Infinity;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function Beta(a, b: Double): Extended;
|
function Beta(a, b: Double): Extended;
|
||||||
begin
|
begin
|
||||||
if (a > 0) and (b > 0) then
|
if (a > 0) and (b > 0) then
|
||||||
@ -268,14 +370,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
// Calculates the (cumulative) t distribution function for DF degrees of freedom
|
// Calculates the (cumulative) t distribution function for DF degrees of freedom
|
||||||
function tDist(x: Double; DF: Integer; OneSided: Boolean): Double;
|
function tDist(x, DF: Double; OneSided: Boolean): Double;
|
||||||
begin
|
begin
|
||||||
Result := betai(0.5*DF, 0.5, DF/(DF + sqr(x)));
|
Result := betai(0.5*DF, 0.5, DF/(DF + sqr(x)));
|
||||||
if OneSided then Result := Result * 0.5;
|
if OneSided then Result := Result * 0.5;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// Returns the density curve for the t statistic with DF degrees of freedom
|
// Returns the density curve for the t statistic with DF degrees of freedom
|
||||||
function tDensity(x: Double; DF: Integer): Double;
|
function tDensity(x, DF: Double): Double;
|
||||||
var
|
var
|
||||||
factor: Double;
|
factor: Double;
|
||||||
begin
|
begin
|
||||||
@ -285,12 +387,23 @@ end;
|
|||||||
|
|
||||||
{ Returns the cumulative probability corresponding to a two-tailed t test with
|
{ Returns the cumulative probability corresponding to a two-tailed t test with
|
||||||
DF degrees of freedom. }
|
DF degrees of freedom. }
|
||||||
function ProbT(t, DF1: double): double;
|
function ProbT(t, DF: double): double;
|
||||||
var
|
var
|
||||||
F: double;
|
F: double;
|
||||||
begin
|
begin
|
||||||
F := t * t;
|
F := t * t;
|
||||||
Result := ProbF(F, 1.0, DF1);
|
Result := ProbF(F, 1.0, DF);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ Returns the t value corresponding to a two-tailed t test probability. }
|
||||||
|
function InverseT(Probability, DF: Double): double;
|
||||||
|
var
|
||||||
|
z, w: double;
|
||||||
|
begin
|
||||||
|
z := InverseNormalDist(Probability);
|
||||||
|
w := z * ((8.0 * DF + 3.0) / (1.0 + 8.0 * DF));
|
||||||
|
Result := sqrt(DF * (exp(w * w / DF) - 1.0));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -590,6 +703,170 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
// It is assumed that xData and yData contain at least 3 elements and
|
||||||
|
// have the same count of elements.
|
||||||
|
procedure Calc_BivariateRegression(const xData, yData: DblDyneVec; AConfLevel: Double;
|
||||||
|
out AResults: TBivariateRegressionResults);
|
||||||
|
var
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
with AResults do
|
||||||
|
begin
|
||||||
|
Count := Length(xData);
|
||||||
|
|
||||||
|
// Calculate means, variances, stddevs
|
||||||
|
Calc_MeanVarStdDevSS(xData, XMean, XVariance, XStdDev, SXX);
|
||||||
|
Calc_MeanVarStdDevSS(yData, YMean, YVariance, YStdDev, SYY);
|
||||||
|
|
||||||
|
SXY := 0;
|
||||||
|
for i := 0 to Count-1 do
|
||||||
|
SXY := SXY + xData[i] * yData[i];
|
||||||
|
|
||||||
|
R := (SXY - XMean * YMean * Count) / ((Count - 1) * XStdDev * YStdDev);
|
||||||
|
StdErrorPredicted := sqrt(1.0 - sqr(R)) * YStdDev * sqrt((Count - 1) / (Count - 2));
|
||||||
|
|
||||||
|
Slope := R * YStdDev / XStdDev;
|
||||||
|
Intercept := YMean - Slope * XMean;
|
||||||
|
|
||||||
|
DF := Count - 2;
|
||||||
|
t := InverseT(AConfLevel, DF);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TBivariateRegressionResults.ConfidenceLimits(x: Double; Upper: Boolean): Double;
|
||||||
|
var
|
||||||
|
yPred, seData: Double;
|
||||||
|
begin
|
||||||
|
yPred := Intercept + Slope * x;
|
||||||
|
seData := StdErrorPredicted * sqrt(1.0 + 1/Count + sqr(x - XMean)/SXX);
|
||||||
|
if Upper then
|
||||||
|
Result := yPred + t*seData
|
||||||
|
else
|
||||||
|
Result := yPred - t*seData;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure Exchange(var a, b: Double);
|
||||||
|
var
|
||||||
|
tmp: Double;
|
||||||
|
begin
|
||||||
|
tmp := a;
|
||||||
|
a := b;
|
||||||
|
b := tmp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Exchange(var a, b: Integer);
|
||||||
|
var
|
||||||
|
tmp: Integer;
|
||||||
|
begin
|
||||||
|
tmp := a;
|
||||||
|
a := b;
|
||||||
|
b := tmp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure Exchange(var a, b: String);
|
||||||
|
var
|
||||||
|
tmp: String;
|
||||||
|
begin
|
||||||
|
tmp := a;
|
||||||
|
a := b;
|
||||||
|
b := tmp;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
||||||
|
var
|
||||||
|
i, j, N: Integer;
|
||||||
|
begin
|
||||||
|
N := Length(X);
|
||||||
|
if (Y <> nil) and (N <> Length(Y)) then
|
||||||
|
raise Exception.Create('[SortOnX] Arrays must have the same length.');
|
||||||
|
if (Z <> nil) and (N <> Length(Z)) then
|
||||||
|
raise Exception.Create('[SortOnX] Arrays must have the same length.');
|
||||||
|
|
||||||
|
for i := 0 to N - 2 do
|
||||||
|
begin
|
||||||
|
for j := i + 1 to N - 1 do
|
||||||
|
begin
|
||||||
|
if X[i] > X[j] then //swap
|
||||||
|
begin
|
||||||
|
Exchange(X[i], X[j]);
|
||||||
|
if Y <> nil then
|
||||||
|
Exchange(Y[i], Y[j]);
|
||||||
|
if Z <> nil then
|
||||||
|
Exchange(Z[i], Z[j]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
// NOTE: The matrix Y is transposed relative to the typical usage in LazStats
|
||||||
|
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
|
||||||
|
var
|
||||||
|
i, j, k, N, Ny: Integer;
|
||||||
|
begin
|
||||||
|
N := Length(X);
|
||||||
|
if N <> Length(Y[0]) then
|
||||||
|
raise Exception.Create('[SortOnX] Arrays X and Y (2nd index) must have the same length');
|
||||||
|
Ny := Length(Y);
|
||||||
|
|
||||||
|
for i := 0 to N-2 do
|
||||||
|
begin
|
||||||
|
for j := i+1 to N-1 do
|
||||||
|
if X[i] > X[j] then
|
||||||
|
begin
|
||||||
|
Exchange(X[i], X[j]);
|
||||||
|
for k := 0 to Ny-1 do
|
||||||
|
Exchange(Y[k, i], Y[k, j]);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure QuickSortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
||||||
|
|
||||||
|
procedure DoQuickSort(L, R: Integer);
|
||||||
|
var
|
||||||
|
I,J: Integer;
|
||||||
|
P: Integer;
|
||||||
|
begin
|
||||||
|
repeat
|
||||||
|
I := L;
|
||||||
|
J := R;
|
||||||
|
P := (L+R) div 2;
|
||||||
|
repeat
|
||||||
|
while CompareValue(X[P], X[I]) > 0 do inc(I);
|
||||||
|
while CompareValue(X[P], X[J]) < 0 do dec(J);
|
||||||
|
if I <= J then begin
|
||||||
|
if I <> J then begin
|
||||||
|
Exchange(X[I], X[J]);
|
||||||
|
if Y <> nil then
|
||||||
|
Exchange(Y[I], Y[J]);
|
||||||
|
if Z <> nil then
|
||||||
|
Exchange(Z[I], Z[J]);
|
||||||
|
end;
|
||||||
|
|
||||||
|
if P = I then
|
||||||
|
P := J
|
||||||
|
else if P = J then
|
||||||
|
P := I;
|
||||||
|
|
||||||
|
inc(I);
|
||||||
|
dec(J);
|
||||||
|
end;
|
||||||
|
until I > J;
|
||||||
|
|
||||||
|
if L < J then
|
||||||
|
DoQuickSort(L, J);
|
||||||
|
|
||||||
|
L := I;
|
||||||
|
until I >= R;
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
DoQuickSort(0, High(X));
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
InitFactLn();
|
InitFactLn();
|
||||||
|
|
||||||
|
@ -21,15 +21,6 @@ function AnySelected(AListbox: TListBox): Boolean;
|
|||||||
procedure ErrorMsg(const AMsg: String);
|
procedure ErrorMsg(const AMsg: String);
|
||||||
procedure ErrorMsg(const AMsg: String; const AParams: array of const);
|
procedure ErrorMsg(const AMsg: String; const AParams: array of const);
|
||||||
|
|
||||||
procedure Exchange(var a, b: Double); overload;
|
|
||||||
procedure Exchange(var a, b: Integer); overload;
|
|
||||||
procedure Exchange(var a, b: String); overload;
|
|
||||||
|
|
||||||
procedure SortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
|
||||||
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
|
|
||||||
|
|
||||||
procedure QuickSortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil); // not 100% tested...
|
|
||||||
|
|
||||||
function CenterString(S: String; Width: Integer): String;
|
function CenterString(S: String; Width: Integer): String;
|
||||||
function IndexOfString(L: StrDyneVec; s: String): Integer;
|
function IndexOfString(L: StrDyneVec; s: String): Integer;
|
||||||
|
|
||||||
@ -107,125 +98,6 @@ begin
|
|||||||
ErrorMsg(Format(AMsg, AParams));
|
ErrorMsg(Format(AMsg, AParams));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure Exchange(var a, b: Double);
|
|
||||||
var
|
|
||||||
tmp: Double;
|
|
||||||
begin
|
|
||||||
tmp := a;
|
|
||||||
a := b;
|
|
||||||
b := tmp;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure Exchange(var a, b: Integer);
|
|
||||||
var
|
|
||||||
tmp: Integer;
|
|
||||||
begin
|
|
||||||
tmp := a;
|
|
||||||
a := b;
|
|
||||||
b := tmp;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure Exchange(var a, b: String);
|
|
||||||
var
|
|
||||||
tmp: String;
|
|
||||||
begin
|
|
||||||
tmp := a;
|
|
||||||
a := b;
|
|
||||||
b := tmp;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure SortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
|
||||||
var
|
|
||||||
i, j, N: Integer;
|
|
||||||
begin
|
|
||||||
N := Length(X);
|
|
||||||
if (Y <> nil) and (N <> Length(Y)) then
|
|
||||||
raise Exception.Create('[SortOnX] Arrays must have the same length.');
|
|
||||||
if (Z <> nil) and (N <> Length(Z)) then
|
|
||||||
raise Exception.Create('[SortOnX] Arrays must have the same length.');
|
|
||||||
|
|
||||||
for i := 0 to N - 2 do
|
|
||||||
begin
|
|
||||||
for j := i + 1 to N - 1 do
|
|
||||||
begin
|
|
||||||
if X[i] > X[j] then //swap
|
|
||||||
begin
|
|
||||||
Exchange(X[i], X[j]);
|
|
||||||
if Y <> nil then
|
|
||||||
Exchange(Y[i], Y[j]);
|
|
||||||
if Z <> nil then
|
|
||||||
Exchange(Z[i], Z[j]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
// NOTE: The matrix Y is transposed relative to the typical usage in LazStats
|
|
||||||
procedure SortOnX(X: DblDyneVec; Y: DblDyneMat);
|
|
||||||
var
|
|
||||||
i, j, k, N, Ny: Integer;
|
|
||||||
begin
|
|
||||||
N := Length(X);
|
|
||||||
if N <> Length(Y[0]) then
|
|
||||||
raise Exception.Create('[SortOnX] Arrays X and Y (2nd index) must have the same length');
|
|
||||||
Ny := Length(Y);
|
|
||||||
|
|
||||||
for i := 0 to N-2 do
|
|
||||||
begin
|
|
||||||
for j := i+1 to N-1 do
|
|
||||||
if X[i] > X[j] then
|
|
||||||
begin
|
|
||||||
Exchange(X[i], X[j]);
|
|
||||||
for k := 0 to Ny-1 do
|
|
||||||
Exchange(Y[k, i], Y[k, j]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure QuickSortOnX(X: DblDyneVec; Y: DblDyneVec = nil; Z: DblDyneVec = nil);
|
|
||||||
|
|
||||||
procedure DoQuickSort(L, R: Integer);
|
|
||||||
var
|
|
||||||
I,J: Integer;
|
|
||||||
P: Integer;
|
|
||||||
begin
|
|
||||||
repeat
|
|
||||||
I := L;
|
|
||||||
J := R;
|
|
||||||
P := (L+R) div 2;
|
|
||||||
repeat
|
|
||||||
while CompareValue(X[P], X[I]) > 0 do inc(I);
|
|
||||||
while CompareValue(X[P], X[J]) < 0 do dec(J);
|
|
||||||
if I <= J then begin
|
|
||||||
if I <> J then begin
|
|
||||||
Exchange(X[I], X[J]);
|
|
||||||
if Y <> nil then
|
|
||||||
Exchange(Y[I], Y[J]);
|
|
||||||
if Z <> nil then
|
|
||||||
Exchange(Z[I], Z[J]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if P = I then
|
|
||||||
P := J
|
|
||||||
else if P = J then
|
|
||||||
P := I;
|
|
||||||
|
|
||||||
inc(I);
|
|
||||||
dec(J);
|
|
||||||
end;
|
|
||||||
until I > J;
|
|
||||||
|
|
||||||
if L < J then
|
|
||||||
DoQuickSort(L, J);
|
|
||||||
|
|
||||||
L := I;
|
|
||||||
until I >= R;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
DoQuickSort(0, High(X));
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function CenterString(S: String; Width: Integer): String;
|
function CenterString(S: String; Width: Integer): String;
|
||||||
var
|
var
|
||||||
|
Reference in New Issue
Block a user