TAChart: Handle numerical overflows during fitting by catching the exception.

git-svn-id: trunk@63618 -
This commit is contained in:
wp 2020-07-22 08:09:47 +00:00
parent 6c06094f0f
commit 39e235c21c
15 changed files with 73 additions and 25 deletions

View File

@ -215,6 +215,10 @@ msgstr "Die Anzahl der Fitparameter kann nicht kleiner als 1 sein."
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "Der Typ des Ausdrucksergebnisses muss integer oder float sein, ist aber \"%s\"." msgstr "Der Typ des Ausdrucksergebnisses muss integer oder float sein, ist aber \"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "Math. Funktion (farb-kodiert)" msgstr "Math. Funktion (farb-kodiert)"

View File

@ -203,6 +203,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "" msgstr ""
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "" msgstr ""

View File

@ -213,6 +213,10 @@ msgstr "Le nombre de paramètres appropriés ne peut pas être inférieur à 1."
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "Le type de résultat d'expression doit être entier ou flottant. On a obtenu \"%s\"." msgstr "Le type de résultat d'expression doit être entier ou flottant. On a obtenu \"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "Séries de cartes de couleurs d'expressions mathématiques" msgstr "Séries de cartes de couleurs d'expressions mathématiques"

View File

@ -213,6 +213,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "A kifejezés típusának egész vagy lebegőpontos számnak kell lennie. Most \"%s\"." msgstr "A kifejezés típusának egész vagy lebegőpontos számnak kell lennie. Most \"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "Színtérkép matematikai kifejezés alapján" msgstr "Színtérkép matematikai kifejezés alapján"

View File

@ -214,6 +214,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "" msgstr ""
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "" msgstr ""

View File

@ -213,6 +213,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "" msgstr ""
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "" msgstr ""

View File

@ -203,6 +203,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "" msgstr ""
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "" msgstr ""

View File

@ -213,6 +213,10 @@ msgstr "O número de parâmetros à preencher não pode ser menor que 1."
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "Tipo de resultado da expressão deve ser inteiro ou flutuante. Obtido \"%s\"." msgstr "Tipo de resultado da expressão deve ser inteiro ou flutuante. Obtido \"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "Série Mapa de cor de expressão matemática" msgstr "Série Mapa de cor de expressão matemática"

View File

@ -213,6 +213,10 @@ msgstr "Независимых переменных не может быть м
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "Тип результата выражения должен быть целым либо вещественным, но сейчас является \"%s\"." msgstr "Тип результата выражения должен быть целым либо вещественным, но сейчас является \"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "Диаграмма с картой цветов по математическому выражению" msgstr "Диаграмма с картой цветов по математическому выражению"

View File

@ -216,6 +216,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "" msgstr ""
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "" msgstr ""

View File

@ -216,6 +216,10 @@ msgstr "Число параметрів апроксимації не може
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "Тип значення виразу повинен бути цілим або дійсним. Отримано \"%s\"." msgstr "Тип значення виразу повинен бути цілим або дійсним. Отримано \"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "Колірна карта" msgstr "Колірна карта"

View File

@ -214,6 +214,10 @@ msgstr ""
msgid "Expression result type must be integer or float. Got \"%s\"." msgid "Expression result type must be integer or float. Got \"%s\"."
msgstr "表达式结果类型必须是整型(integer)或浮点型(float).得到\"%s\"." msgstr "表达式结果类型必须是整型(integer)或浮点型(float).得到\"%s\"."
#: tachartstrconsts.rserrnumericaloverflow
msgid "Numerical overflow."
msgstr ""
#: tachartstrconsts.rsexpressioncolormapseries #: tachartstrconsts.rsexpressioncolormapseries
msgid "Math expression color map series" msgid "Math expression color map series"
msgstr "数学表达式彩色图系列" msgstr "数学表达式彩色图系列"

View File

@ -148,6 +148,7 @@ resourcestring
rsErrFitNoFitParams = 'No fit parameters specified.'; rsErrFitNoFitParams = 'No fit parameters specified.';
rsErrFitSingular = 'Fitting matrix is (nearly) singular.'; rsErrFitSingular = 'Fitting matrix is (nearly) singular.';
rsErrFitNoBaseFunctions = 'Not enough user-provided base functions.'; rsErrFitNoBaseFunctions = 'Not enough user-provided base functions.';
rsErrNumericalOverflow = 'Numerical overflow.';
rsFitNumObservations = 'Number of observations'; rsFitNumObservations = 'Number of observations';
rsFitNumFitParams = 'Number of fit parameters'; rsFitNumFitParams = 'Number of fit parameters';
rsFitDegreesOfFreedom = 'Degrees of freedom'; rsFitDegreesOfFreedom = 'Degrees of freedom';

View File

@ -35,7 +35,8 @@ type
fitMoreParamsThanValues, // There are more fitting parameters than data values fitMoreParamsThanValues, // There are more fitting parameters than data values
fitNoFitParams, // No fit parameters specified fitNoFitParams, // No fit parameters specified
fitSingular, // Matrix is (nearly) singular fitSingular, // Matrix is (nearly) singular
fitNoBaseFunctions // No user-provided base functions fitNoBaseFunctions, // No user-provided base functions
fitOverflow // Numerical overflow
); );
TFitResults = record TFitResults = record
@ -201,9 +202,6 @@ end;
- Numerical Recipes, Ch 14, Modelling of data, General linear least squares } - Numerical Recipes, Ch 14, Modelling of data, General linear least squares }
function LinearFit(const x, y, dy: TArbFloatArray; function LinearFit(const x, y, dy: TArbFloatArray;
FitParams: TFitParamArray): TFitResults; FitParams: TFitParamArray): TFitResults;
const
TOO_LARGE = 1E100;
TOO_SMALL = 1.0 / TOO_LARGE;
var var
alpha: TArbFloatArray = nil; alpha: TArbFloatArray = nil;
beta: TArbFloatArray = nil; beta: TArbFloatArray = nil;
@ -297,11 +295,6 @@ begin
kj := k * mfit + j; kj := k * mfit + j;
jk := j * mfit + k; jk := j * mfit + k;
alpha[kj] := alpha[jk]; alpha[kj] := alpha[jk];
if not InRange(abs(alpha[kj]), TOO_SMALL, TOO_LARGE) then
begin
Result.ErrCode := fitSingular;
exit;
end;
end; end;
// Solve equation system // Solve equation system

View File

@ -1821,6 +1821,7 @@ begin
fitNoFitParams : Result := rsErrFitNoFitParams; fitNoFitParams : Result := rsErrFitNoFitParams;
fitSingular : Result := rsErrFitSingular; fitSingular : Result := rsErrFitSingular;
fitNoBaseFunctions : Result := rsErrFitNoBaseFunctions; fitNoBaseFunctions : Result := rsErrFitNoBaseFunctions;
fitOverflow : Result := rsErrNumericalOverflow;
else else
raise EChartError.CreateFmt('[%s.ErrorMsg] No message text assigned to error code #%d.', raise EChartError.CreateFmt('[%s.ErrorMsg] No message text assigned to error code #%d.',
[NameOrClassName(self), ord(ErrCode)]); [NameOrClassName(self), ord(ErrCode)]);
@ -1885,25 +1886,30 @@ var
end; end;
// Execute the polynomial fit; the degree of the polynomial is np - 1. // Execute the polynomial fit; the degree of the polynomial is np - 1.
fitRes := LinearFit(xv, yv, dy, FFitParams); try
FErrCode := fitRes.ErrCode; fitRes := LinearFit(xv, yv, dy, FFitParams);
if fitRes.ErrCode <> fitOK then
exit;
// Store values of fit parameters. FErrCode := fitRes.ErrCode;
// Note: In case of exponential and power fit equations, the first fitted if fitRes.ErrCode <> fitOK then
// parameter is the logarithm of the "real" parameter. It needs to be exit;
// transformed back to real units by exp function. This is done by the
// getter of the property
for i:= 0 to High(FFitParams) do
FFitParams[i].Value := fitRes.ParamValues[i];
// Analysis of variance, variance-covariance matrix // Store values of fit parameters.
FFitStatistics.Free; // Note: In case of exponential and power fit equations, the first fitted
FFitStatistics := TFitStatistics.Create(fitRes, 1 - FConfidenceLevel); // parameter is the logarithm of the "real" parameter. It needs to be
// transformed back to real units by exp function. This is done by the
// getter of the property
for i:= 0 to High(FFitParams) do
FFitParams[i].Value := fitRes.ParamValues[i];
// State of the fit // Analysis of variance, variance-covariance matrix
FState := fpsValid; FFitStatistics.Free;
FFitStatistics := TFitStatistics.Create(fitRes, 1 - FConfidenceLevel);
// State of the fit
FState := fpsValid;
except
FErrCode := fitOverflow;
end;
end; end;
begin begin