Lazarus

Programming => Packages and Libraries => Lazarus Extra Components => Topic started by: erik2727 on September 03, 2020, 02:58:21 am

Title: Lmath ulogifit samples
Post by: erik2727 on September 03, 2020, 02:58:21 am
Hi,

I was looking for some samples on how to use ulogifit for 4 parameters logistic curve fit,
Could someone share some tips or guide please? Below are my code snippet, not sure if the TVector B parameter result output is correct or not ?


var

 X:array [0..9] of Float=(0,1,2,3,4,5,6,7,8,9,10);
 Y:array [0..9] of Float=(10,11,25,36,82,90,106,201,301,403);
 TX,TY:TVector;
  vecB: array of Float;
  B: TVector;
  MatV: TMatrix;
  beta,alpha:Float;
  A1,B1,N:Float;

begin

 TX:=X;
TY:=Y;
DimVector(TX,10);
DimVector(TY,10);
  SetLength(vecB,5);
  B := vecB;
 
  DimMatrix(MatV, 0, 4);
  LogiFit(TX, TY, 1, 9,true,true, 1000, 0.001, B, MatV); 

A1:=B[0];
B1:=B[1];
alpha:=B[2];
beta:=B[3];
N:=B[4];
Title: Re: Lmath ulogifit samples
Post by: Paolo on September 13, 2020, 01:06:07 pm
I don't know about LogiFit, but  I see something wrong in your code:

1) you declare X : array [0..9], this means that you have 10 elements in the array, but you initialize 11 elements ! from 0 to 10, I think this should not compile !
2) why declare vecB : arrray of float and not as TVector !
3) by using DimMatrix(MatV, 0, 4) are you saying that the matrix has one dimension = 0 ! I think also this should not complie, it should be DimMAtrix(MatV, 5, 5) according to matrix 5x5 = [0..4,0..4]. (Maybe the martix is just an output so it is the LogiFit that domesnions it properly, I don't know.
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 17, 2020, 06:07:42 am
Hi,

If you don't know lmath especially logistics mathematical functions in detail, i suggest you don't simply give your
 comments, pascal blueprint are based on Fortran!


First X element should be 1 not zero, rest of the
code compile successfully, readup Lmath what is underlying principle and basis on model construction, I has compared the result with famous C++ non linear solver just like to know why this algorithm assume highest k carrying capacity is the actual high end number and deduce  rest of parameters bases on fixed preset as I have no access to Original Fortran 90 solver
Title: Re: Lmath ulogifit samples
Post by: Paolo on September 21, 2020, 01:51:50 pm
Hi, I admit to have replaied too hasty (in the attempt to help in someway).
Bye.
Title: Re: Lmath ulogifit samples
Post by: alanphys on September 21, 2020, 03:02:13 pm
Hi

Have a look at the regexlin.pas demo in the demo/bgi/regmodel directory of LMath.

Regards
Title: Re: Lmath ulogifit samples
Post by: wp on September 21, 2020, 04:55:59 pm
I was looking for some samples on how to use ulogifit for 4 parameters logistic curve fit,
Could someone share some tips or guide please?
Enclosed is a demo project performing a logistic fit to synthesized data. In the "Input parameters" box the coefficients of the logistic function can be specified for creation of data. In the "Start parameters" you must provide estimates for these coefficients with which the fit should start, they should not be off too much, otherwise numerical overflows can occur depending on the choice of the fitting algorithm (I found that the "Simplex algorithm" seems to be more tolerant than the default "Marquardt algorithm"). Click "Create data" to create the data to be fitted, then "Calc fit" to execute the fit. The fitted curve is drawn over the input data, and the fitted parameters are listed.

var
 X:array [0..9] of Float=(0,1,2,3,4,5,6,7,8,9,10);
 Y:array [0..9] of Float=(10,11,25,36,82,90,106,201,301,403);
...
DimVector(TX,10);
DimVector(TY,10);
... 
  DimMatrix(MatV, 0, 4);
  LogiFit(TX, TY, 1, 9,true,true, 1000, 0.001, B, MatV); 
I agree with Paolo that there is a problem with the indices. The 3rd and 4th parameters of the LogiFit procedure are the start and end index of the data array provided as first and second parameter. Since DimVector() internally simply calls Setlength() which creates a 0-based array the 3rd LogiFit parameter must be 0 rather than 1; the 4th parameter (last array index) is correct. And the matrix MatV is an m x m matrix where m is the count of fit parameters (5, here); so, the DimMatrix() call must be DimMatrix(MatV, 5, 5); each index i,j in MatV[i,j] then runs from 0 to 4
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 22, 2020, 03:17:53 pm
Hi,

Thank you so much  to those who have responded, I  pursuit another non linear fit  solution to my test data with the following code snippets  using modify logistic growth model equation, the output obtained was comparable and almost identical to that of the well known C++ nonlinear solver yield  , the most challenging task of using this method is the proper coding of  partial derivative apply to function parameters required by  Jacobian matrix as well as the best guess input estimate for the parameters   



function RegFunc(X : Float; B1 : TVector) : Float;
{B1[1]=k,B1[2]=C,B1[3]=b }
{y=k/1+(X/C)^b}

begin
  RegFunc := B1[1] / (1+Math.Power(X/B1[2],B1[3]));
end;

procedure DerivProc(X, Y : Float; B1, D : TVector); {Jacobian Matrix}
{B1[1]=k,B1[2]=C,B1[3]=b }

begin
  D[1]:=1/ (1+Math.Power(X/B1[2],B1[3])); {pdk}
  D[2]:=B1[1]*Math.Power(X,B1[3])*B1[3]*Math.Power(B1[2],(-B1[3]-1))/Math.Power(1+Math.Power(X/B1[2],B1[3]),2);  {pdc}
  D[3]:=-B1[1]*Math.Power((X/B1[2]),B1[3])*Ln(X/B1[2])/Math.Power(1+Math.Power(X/B1[2],B1[3]),2); {pdb}

end;


procedure Multi_Fit();


  FirstPar = 1;       { Index of first fitted parameter }
  LastPar  = 3;       { Index of last fitted parameter }
  MaxIter  = 1000;    { Max. number of iterations }
  Tol      = 1.0E-3;  { Required precision }
  Alpha    = 0.05;    { Significance level }


  var
    B1:TVector;
    V:TMatrix;
    N1:integer ;      { Number of points }

begin
  DimVector(B1,LastPar);
  DimMatrix(V, LastPar, LastPar);
  N1:= ??    {set the number of data point to be fitted}
  // set algorithm
  SetOptAlgo(NL_SIMP);

  //initial estimate input to solver
  B1[1]:= ???
  B1[2]:= ???
  B1[3]:= ???


  NLFit(@RegFunc, @DerivProc, TX, TY, 1, N1, MaxIter, Tol,
          B1, FirstPar, LastPar, V);

   ShowMessage('B1[0..N] = ' + FloatToStr(B1[1]) + '/' + FloatToStr(B1[2]) +
    '/' + FloatToStr(B1[3]));


end;
Title: Re: Lmath ulogifit samples
Post by: wp on September 22, 2020, 04:35:44 pm
Is this a question?

I doubt that your procedure is correct. I must say that it's been a long time that I had been able to calculate partial derivatives by myself. Today I call Wolfram Alpha and enter the expression to be differentiated: "derivative  of <expression>". Your expression is
Code: [Select]
y := k / (1+(x/c)^b)Since Wolfram Alpha only calculates a derivative with respect to a variable named x I do a replacement: When I want the partial derivative with respect to b I replace your b by x and your x by a new variable A:
Code: [Select]
derivative of k / (1 + (A/c)^x)The result is
Code: [Select]
dy/dx = -k * ((A/C)^x * ln(A/C)) / ( (A/C)^x + 1)^2or, with the original variables
Code: [Select]
dy/db = -k * (x/C)^b * ln(x/C)) / ( (x/C)^b + 1)^2Part of it is looking like your pdb =  D[3], but yours is lacking the denominator...

For calculating the derivative with respect to C I enter
Code: [Select]
derivative of k / (1 + (A/x)^b)and get the result
Code: [Select]
dy/dx = b * k *  (A/x)^b / ( x * ((A/x)^b - 1)^2 )or, with our variables
Code: [Select]
dy/dC = b * k * (x/C)^b / (C * ((x/C)^b - 1)^2)Again, this is different from your equation for pdc = D{2].

I don't insist on that my results are correct either, there may be typos everywhere... I just want to say: please check your result carefully.

Another (possible) issue refers to the indices, again. This is the declaration of LMath for DimVector (taken from unit utypes):
Code: Pascal  [Select][+][-]
  1. { Creates floating point vector V[0..Ub] }
  2. procedure DimVector(var V : TVector; Ub : Integer); overload;
As the comment says, the procedure creates a 0-based vector, the first element has index 0, the last element has index Ub. So, your function requires 3 arguments, k, C, and b. Since you call DimVector(B, lastPar), with lastPar 3, you are creating a vector with 4 elements, not three, i.e. you ignore the 1st element with index 0. As long as you create more elements then needed there is no problem with this (except for the wasted memory). But you really must keep in mind that this practice is against the Lazarus/FPC  convention. Almost all arrays (except for strings) begin with index 0 and expect the array element with this index to contain valid information. Therefore, I'd expect that you will sooner or later run into problems when stuffing 1-based arrays into 0-based memory allocation.

Suppose you want to display the fit parameters in a listbox. For this purpose you iterate through your pseudo-1-based array B and add the numbers as strings to the listbox:

Code: Pascal  [Select][+][-]
  1. for i := 1 to lastPar do
  2.   Listbox.Items.Add(FormatFloat('0.00000', B[i]);

Now you want to display the second parameter in a label; since the parameter is already converted to string you take the copy from the list box:

Code: Pascal  [Select][+][-]
  1.   Label1.Caption := Listbox.Items[2];

No! The items in the listbox are 0-based, but you think 1-based, you must use ListBox.Items[1]! Whenever I mixed 0-based and 1-based storage I ran into lots of trivial, but hard-to-find problems.

Therefore, I would like you to reconsider this practice and forget your obvious FORTRAN roots. The Pascal-compatible way would be to really use the 0-based array:
Code: Pascal  [Select][+][-]
  1. const
  2.   lastPar = 2;
  3. ...
  4.   DimVector(B, lastPar);
  5. ...
  6.   B[0] := k;
  7.   B[1] := C;
  8.   B[2] := b;  // of course, this will not compile...
  9. ...
  10.   D[0] := ... {pdk}
  11.   D[1] := ... {pdc}
  12.   D[2] := ... {pdb}
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 22, 2020, 06:03:08 pm
Hi ,

I have vetted my result with few defacto  c++ nonlinear solver of which one is the GNU GSL library, the final result is what matter most, have I done  a wrong derivative somehow ,  I may not be able to obtain a default optimum solution , by the way , my main programming language root is C++!!! and I am not a rookie, the reason why I put up this is Lmath or Dmath manual are not very comprehensive and confusing in presenting the solution. 

As long as the result is vetted independently  , , I don't have time to   verify your so called computed derivative, I don't see why computed dy/dk still got k variable when
k*(Constant) is just  constant as far as simple Jacobain matrix of ith row is concern  .

ps.  missing denominator added to orginal

Matlab diff result as below:=

f=k/((x^b/c^b) + 1)

∂f/∂ k=
1/(x^b/c^b + 1)

∂f/∂c=
(b*k*x^b)/(c^(b + 1)*(x^b/c^b + 1)^2)


∂f/∂b=
-(k*((x^b*log(x))/c^b - (x^b*log(c))/c^b))/(x^b/c^b + 1)^2

      k
f=  ──────────
         -b   b
  1 + c  ⋅x

∂f/∂k=


         1
 ──────────
         -b   b
  1 + c  ⋅ x

∂f/∂c=


        -b      b
     b⋅c  ⋅k ⋅x
  ───────────────
                      2
     ⎛       -b  b  ⎞
  c⋅⎝1 + c  ⋅x    ⎠


∂f/∂b=

     ⎛ -b  b            -b  b          ⎞
  k⋅⎝c  ⋅x ⋅log(c) - c  ⋅x ⋅log(x) ⎠
  ─────────────────────────────────
                             2
            ⎛      -b   b  ⎞
            ⎝1 + c  ⋅x    ⎠




 I also could not understand why someone  just like keep on commenting on the index array LB.. UB , read what LMath manual was stating ,

 TMatrix  := total number of independent variable
0..2 is two elements  or 3 elements in total ???????

parameters; V = inverse matrix. Its dimentions must be [Lb..Ub, Lb..Ub],
and also look into the sample programme exhibit ,


Extract of the Lmath sample from regnlin.pas

function RegFunc(X : Float; B : TVector) : Float;
begin
  RegFunc := B[1] * Exp(- B[2] * X);
end;

procedure DerivProc(X, Y : Float; B, D : TVector);
begin
  D[1] := Exp(- B[2] * X);
  D[2] := - B[1] * X * D[1];
end;

 
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 22, 2020, 06:29:23 pm
Hi

Have a look at the regexlin.pas demo in the demo/bgi/regmodel directory of LMath.

Regards
By the way, I have committed BGI demo projects which compile and work under Windows 64. See Trunk.
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 22, 2020, 06:38:38 pm
I agree with Paolo that there is a problem with the indices. The 3rd and 4th parameters of the LogiFit procedure are the start and end index of the data array provided as first and second parameter. Since DimVector() internally simply calls Setlength() which creates a 0-based array the 3rd LogiFit parameter must be 0 rather than 1; the 4th parameter (last array index) is correct. And the matrix MatV is an m x m matrix where m is the count of fit parameters (5, here); so, the DimMatrix() call must be DimMatrix(MatV, 5, 5); each index i,j in MatV[i,j] then runs from 0 to 4
DimVector() and DimMatrix(), unlike SetLength(), take highest index of an array as a parameter. That is, DimVector(M) calls SetLength(M+1). Same is true for DimMatrix. So, if you call DimMatrix(5,5), you can use indices from 1 to 5.
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 22, 2020, 06:48:47 pm
hi,

glorfin (Viatcheslav V. Nesterov)

Is there a procedure in Lmath  to do away with Jacobian matrix for nonlinear regression fit similar to c++ gsl library where jacobian matrix can be optional or not?

Just realise and Look as if the jacobian matrix can be coded as empty procedure for max of 3 parameters  in Lmath afterall and yet still can get final output, great!!
Title: Re: Lmath ulogifit samples
Post by: wp on September 22, 2020, 08:00:53 pm
So, if you call DimMatrix(5,5), you can use indices from 1 to 5.
Sorry to be insistent: While I know that this is caused by the math literature where all vectors and matrices begin with index 1 I think it is a bad concept to abuse standard dynamic arrays for 1-based arrays. As a consequence, the user is on his own, there is no help from the compiler or from run-time errors. As an example, the user of LMath must never mix LMath routines with the routines of the standard Math unit unless he is very aware what he is doing.

The following program calculates the average value of the components of a 5-dim vector. The vector is assumed to be 1-based and is created by LMath. The mean is calculated by the function Mean() in unit uMeanSD. Fine.

But now imagine that this a part of a large program, and somebody somewhere else has to calculate the mean again. He is not familiar with LMath and tries to avoid it. He checks the type TVector and sees: it is an array of float. Ah - there is a ready-made routine in the Math unit. But the result is wrong because Math.Mean runs over all elements of the array, including the 0-th element. There is nothing which tells this user that he must not access the index 0. No warning, no error messsage.

Another issue is that being an array of float the function Length() can be applied to a TVector - the result will be off by 1 for a 1-based vector. Same with the function Low().

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. uses
  4.   math,
  5.   uTypes, umeansd;
  6.  
  7. var
  8.   v: TVector;
  9.   i: Integer;
  10.  
  11. begin
  12.   RandSeed := 0;
  13.   DimVector(v, 5);
  14.  
  15.   for i := 1 to 5 do
  16.     v[i] := Random;
  17.  
  18.   WriteLn('Mean(LMath) = ', umeansd.Mean(v, 1, 5):0:3);  // ---> 0.661
  19.   WriteLn('Mean(math)  = ', math.Mean(v):0:3);           // ---> 0.551
  20.  
  21.   ReadLn;
  22.  
  23. end.  
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 22, 2020, 08:47:00 pm
Hi

Please Don't simply change LMath coded routine and break all the compatibility with previous version just
because  1  and not zero being  set as  starting index option instead, it would be a big nightmares to re-programme existing coded block  from scratch !!!

In my view , TVector.TMatrix  is also  not advisable to  assume as a  regular float array block with 0 as initial, it is much better to  abide by classical mathematics principle i,j concept
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 23, 2020, 11:29:26 am
As an example, the user of LMath must never mix LMath routines with the routines of the standard Math unit unless he is very aware what he is doing.

Yes, that is exactly why I try to make LMath self-contained without a necessety to use Math together with it.
In part I agree with you. But problem is that a lot of functions in DMath (which later became LMath) were translated from Pascal, and rewriting them for 0-based arrays can lead not only to broken compatibility with older versions, but also introduce a lot of bugs in process.

Therefore, internally LMath will remain largely 1-based.

However, in many cases there are Lb, Ub parameters, and in such cases one can freely set Lb = 0 and use effectively 0-based TVector or TMatrix. In uMeanSD you can freely call uMeanSD(V,0,5).


If there are no such params, look at the documentation for array base.
Title: Re: Lmath ulogifit samples
Post by: wp on September 23, 2020, 11:44:00 am
Just an idea: The attached program introduces a TVector as a separate type (not a renamed "array of float"), so that the standard functions Length() and Low(), as well as the math functions Mean(), Sum() etc can no longer be applied. Using an additional (optional) parameter in DimVector the user can decide whether he wants 0 or 1 as the first index. Using {$mode Delphi} or {$mode objfpc} along with {$modeswitch advancedrecords} this new type could be made to behave like a simple array to the outside.

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. {$mode Delphi}
  4.  
  5. uses
  6.   SysUtils;
  7.  
  8. type
  9.   float = double;
  10.  
  11.   TVector = record
  12.   private
  13.     FValues: Array of Float;
  14.     FOneBased: Boolean;
  15.     function GetValue(AIndex: Integer): Float; inline;
  16.     procedure SetValue(AIndex: Integer; AValue: Float); inline;
  17.   public
  18.     property Value[AIndex: Integer]: Float read GetValue write SetValue; default;
  19.     property OneBased: boolean read FOneBased;
  20.   end;
  21.  
  22.   function TVector.GetValue(AIndex: Integer): Float;
  23.   begin
  24.     if FOneBased then dec(AIndex);
  25.     Result := FValues[AIndex];
  26.   end;
  27.  
  28.   procedure TVector.SetValue(AIndex: Integer; AValue: Float);
  29.   begin
  30.     if FOneBased then dec(AIndex);
  31.     FValues[AIndex] := AValue;
  32.   end;
  33.  
  34. procedure DimVector(var V: TVector; ADim: Integer; IsOneBased: Boolean = true);
  35. begin
  36.   V.FOneBased := IsOneBased;
  37.   SetLength(V.FValues, ADim);
  38. end;
  39.  
  40. function Dim(V: TVector): Integer;
  41. begin
  42.   Result := Length(V.FValues);
  43. end;
  44.  
  45. var
  46.   v: TVector;
  47.   i: Integer;
  48.  
  49. begin
  50.   DimVector(v, 5, false);  // Create a 0-based 5-dim vector
  51.   v[0] := 1.0;
  52.   v[1] := 2.0;
  53.   v[2] := 3.0;
  54.   v[3] := 4.0;
  55.   v[4] := 5.0;
  56.   WriteLn('0-based vector');
  57.   for i := 0 to Dim(V)-1 do
  58.     WriteLn('v[',i,']=',v[i]:0:3);
  59.  
  60.   WriteLn;
  61.  
  62.   DimVector(v, 5);  // Create a 1-based 5-dim vector
  63.   v[1] := 1.0;
  64.   v[2] := 2.0;
  65.   v[3] := 3.0;
  66.   v[4] := 4.0;
  67.   v[5] := 5.0;
  68.   WriteLn('1-based vector');
  69.   for i := 1 to  Dim(V) do
  70.     WriteLn('v[',i,']=', v[i]:0:3);
  71.  
  72.   // Access element at index 0 --> RunError(201) when range and overflow checking are active
  73.   WriteLn('v[0]=',v[0]);
  74.  
  75.   ReadLn;
  76. end.

I am not claiming this to be the ultimate solution; it could be a bit slower than the current one with dynamic array because of the frequent addition/subtraction of 1 in case of the 1-based case. As I said: just an idea...
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 23, 2020, 12:17:51 pm
> TVector as a separate type
Something in direction of TPoints in lmPointsVec from lmComponents?  :)
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 23, 2020, 12:41:27 pm
hi,

Agreed , refer to manual when in doubt , got stuck , shout for help in forum . No point reinvent the wheel when everything is working orderly!
Title: Re: Lmath ulogifit samples
Post by: wp on September 23, 2020, 01:10:11 pm
> TVector as a separate type
Something in direction of TPoints in lmPointsVec from lmComponents?  :)
Yes, similar. But "my" TVector is a record (no class like TPoints) and, therefore, there is no explicit need for destruction.
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 23, 2020, 01:40:57 pm
Hi,

Put this up for future feature request or enhancement, I am ok as long as no performance degrade or issues
 :D
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 23, 2020, 05:43:22 pm
> TVector as a separate type
Something in direction of TPoints in lmPointsVec from lmComponents?  :)
Yes, similar. But "my" TVector is a record (no class like TPoints) and, therefore, there is no explicit need for destruction.
I thought about it. In fact, I have, for my own needs, similar class called TReals, but problem here is that call to GetValue/SetValue each time one wants to assign/read value of an array is very inefficient. If you noticed,  variable Points in TPoints is public to get direct access to array elements. Inlining function would make it somewhat faster, but still, there is additional comparison and additional assignment.
Title: Re: Lmath ulogifit samples
Post by: wp on September 24, 2020, 01:14:49 pm
@glorfin: Re-thinking "my" TVector in reply #15 again, I see that it may open another box of Pandora since the same type TVector can be both one-based as well as zero-based. Assume v0 is a zero-based and v1 a 1-based TVector. What if the users tries to calculate their sum, v0 + v1? Will he add (v0[0]+v1[1], v0[1]+v1[2], ...)? Not very logical -- it is a bad idea to allow for both worlds.
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 24, 2020, 01:32:08 pm
Hi,

In my view, the whole Tvector structure to store data may have been  restricted by Pascal bounded fixed array concept, it would be good to borrow c++ vector design to auto increase the capacity as needed.

I have come across few c++ math numerial library having the same issues simply because the data are bind to array, the one that offer flexibility and satisfy my need is boost c++ ode where data both input and output are stored in vector<any> format as i dealt with ode45 and numerical advanced calculus in my research.

This is just an expression of opinion, not requesting any major modification to existing Tvector concepts as I know is a dangerous and daunting task to redesign existing library
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 24, 2020, 02:41:52 pm
@erik2727
Free Pascal dynamic arrays (including TVector) can be resized with SetLength(). Moreover, there are Insert() and Delete() procedures which insert or delete elements and resize arrays accordingly. However, I do not like an idea that an array must be completely reallocated at each insert/delete. LMath has a unit uVectorHelper, where Insert and Delete do not change length, but in Insert last value is lost, and in Delete last value is set to "0".
Title: Re: Lmath ulogifit samples
Post by: erik2727 on September 24, 2020, 03:25:10 pm
hi,

By virtue of the fact that  TVector is indeed an  dynamic array  , would calling DimVector at anytime   resize an allocated array or not as Lmath manual  only briefly state below  quoted statement 

Sorry I don't quite understand what vector meant in free  pascal dialect ,is it a record or container type ? I also look into free pascal Numlib vector declaration

LMath

Vector  type      Matrix type    Base variable
TVector               TMatrix       Floating point number (type Float)

 Creates a vector V[0..Ub] based on a type corresponding to a parameter
(Float, Integer, Complex, RealPoint, Boolean; Strings. In DMath, procedures
with di erent names were used; LMath uses overloading).


NumLib

Vectors

NumLib often passes vectors to procedures as one ArbFloat plus some integer value. This ArbFloat value is the first value of an array containing the vector, the integer is the count of elements used from this array. Internally an array type is mapped over the first value in order to access the other array elements. This way both 0- and 1-based arrays as well as static and dynamic arrays can be passed to the functions and procedures of NumLib.
Title: Re: Lmath ulogifit samples
Post by: glorfin on September 24, 2020, 06:45:03 pm
@erik2727:
In principle, vector is just one-dimentional array. In Pascal there are static and dynamic arrays:
https://www.freepascal.org/docs-html/ref/refsu14.html

Importantly, static array may be declated with any indexing you want:
Code: Pascal  [Select][+][-]
  1. type
  2.   TFortranArray = array[1..122] of float;
  3.   TColors = (Red,Green,Blue);
  4.   TColorArray = array[TColors] of byte;
  5.  
but dynamic arrays are always 0-based.
In LMath,
Code: Pascal  [Select][+][-]
  1. TVector = array of Float;
  2. TCompVector = array of Complex;
  3.  
etc.
So, all T*Vector types in LMath are dynamic arrays, internally 0-based. When fortran-style functions of LMath use "1-based" arrays, they simply ignore first element, with index "0".
Call to system function SetLength(V,10) allocates dynamic array with 10 elements, indexed  from V[0] to V[9]. If we think "fortran-style", we would expect highest index 10. Therefore, LMath defines own wrapper function DimVector, where not length, but highest index of an array is passed: DimVector(V,10) allocates V[0] to V[10].

And yes, DimVector and SetLength resize an allocated array and copy all existing values into new array, of cource truncating if needed.
Title: Re: Lmath ulogifit samples
Post by: nanobit on September 24, 2020, 07:25:55 pm
Just from reading the thread, it seems LMath allows this:
1) array-content, Lb, Ub can be 0-based
2) array-content (after reserved zero), Lb, Ub can be 1-based,
in this case I see another potential option:
zArray := @internalArray[1]; zLb := Lb-1; zUb := Ub-1;
Now, 0-based algorithms are possible with pointermath index-notation:
zArray[zLb], zArray[zUb]
TinyPortal © 2005-2018