LazStats: Fix crash due to range check error in DescriptiveUnit

git-svn-id: https://svn.code.sf.net/p/lazarus-ccr/svn@7749 8e941d3f-bd1b-0410-a28a-d453659cc2b4
This commit is contained in:
wp_xxyyzz
2020-10-05 21:00:45 +00:00
parent d16c17ff86
commit 2d3368e257
2 changed files with 20 additions and 28 deletions

View File

@ -49,13 +49,7 @@
<DebugInfoType Value="dsDwarf2Set"/>
<UseHeaptrc Value="True"/>
<TrashVariables Value="True"/>
<UseExternalDbgSyms Value="True"/>
</Debugging>
<Options>
<Win32>
<GraphicApplication Value="True"/>
</Win32>
</Options>
</Linking>
</CompilerOptions>
</Item2>

View File

@ -95,7 +95,7 @@ type
private
function GetReportFrame(APageIndex: Integer): TReportFrame;
procedure WriteToReport(Stats: TDescriptiveStats; AVarName: String; AReport: TStrings);
procedure zScoresToGrid(AColIndex: Integer; const AColsSelected: IntDyneVec;
procedure zScoresToGrid(AColIndex: Integer; var AColsSelected: IntDyneVec;
AMean, AStdDev: Double);
protected
@ -380,35 +380,30 @@ end;
procedure TDescriptiveFrm.Compute;
var
cellString: String;
i, j: Integer;
noSelected: Integer;
nSelected: Integer;
selected: IntDyneVec = nil;
page: TTabSheet;
reportFrame: TReportFrame;
lReport: TStrings;
lStats: TDescriptiveStats;
begin
noSelected := SelList.Items.Count;
if noSelected = 0 then
nSelected := SelList.Items.Count;
if nSelected = 0 then
begin
MessageDlg('No variables selected.', mtError, [mbOK], 0);
exit;
end;
SetLength(selected, noSelected);
SetLength(selected, nSelected);
// Find column index of selected variables
for i := 0 to noSelected - 1 do
begin
cellstring := SelList.Items[i];
for j := 1 to NoVariables do
if cellstring = OS3MainFrm.DataGrid.Cells[j,0] then selected[i] := j;
end;
for i := 0 to nSelected - 1 do
selected[i] := OS3MainFrm.DataGrid.Rows[0].IndexOf(SelList.Items[i]);
// Create a tabsheet with ReportFrame for each selected variable (in addition to the built-in one)
if noSelected > PageControl.PageCount then
if nSelected > PageControl.PageCount then
begin
for i := 1 to noSelected-1 do // we do not create a tab for the first variable - it exists by default
for i := 1 to nSelected-1 do // we do not create a tab for the first variable - it exists by default
begin
page := TTabSheet.Create(PageControl);
page.Parent := PageControl;
@ -420,26 +415,27 @@ begin
end;
// Remove excess pages from previous session
while PageControl.PageCount > noSelected do
while PageControl.PageCount > nSelected do
PageControl.Pages[PageControl.PageCount-1].Free;
// Every tab gets the name of the corresponding variable.
for i := 0 to NoSelected-1 do
for i := 0 to nSelected-1 do
PageControl.Pages[i].Caption := OS3MainFrm.DataGrid.Cells[selected[i], 0];
//
// Write report
lReport := TStringList.Create;
if not CaseChk.Checked then
lStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid)
else
lStats := TDescriptiveStats.Create(OS3MainFrm.DataGrid, selected);
try
for i := 0 to noSelected-1 do
for i := 0 to nSelected-1 do
begin
// Analyze the data and get descriptive stats
lStats.Analyze(selected[i]);
// Store z values, (value - mean) / stdDev, to grid, if needed
if zScoresToGridChk.Checked then
zScoresToGrid(selected[i], selected, lStats.Mean, lStats.StdDev);
// Write descriptive stats to report
@ -700,7 +696,7 @@ end;
procedure TDescriptiveFrm.zScoresToGrid(AColIndex: Integer;
const AColsSelected: IntDyneVec; AMean, AStdDev: Double);
var AColsSelected: IntDyneVec; AMean, AStdDev: Double);
var
i, idx: Integer;
value, zValue: Double;
@ -725,10 +721,12 @@ begin
begin
if CaseChk.Checked then
begin
if not DataProcs.ValidValue(i, AColsSelected[AColIndex]) then continue;
if not DataProcs.GoodRecord(i, Length(AColsSelected), AColsSelected) then continue;
end
else
if not DataProcs.GoodRecord(i, Length(AColsSelected), AColsSelected) then continue;
begin
if not DataProcs.ValidValue(i, AColIndex) then continue;
end;
value := StrToFloat(OS3MainFrm.DataGrid.Cells[AColIndex, i]);
zValue := (value - AMean) / AStdDev;