home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / PASCAL / TPTOOL4.ZIP / POLY.INC < prev    next >
Encoding:
Text File  |  1987-03-28  |  5.5 KB  |  242 lines

  1.  
  2. #log Polynomial interpolation
  3.  
  4. (*
  5.  *  This program fits least-squares polynomials to bivariate
  6.  *  data, using an orthogonal polynomial method.  
  7.  *
  8.  *  Equation form:
  9.  *       Y := C0 + C1 * X + C2 * X^2 + C3 * X^3 ...  + Cn * X^n
  10.  *
  11.  *  The most common use of this technique is for computerizing
  12.  *  graphical or tabular data.  the equation requires much less
  13.  *  space and no interpolating.
  14.  *
  15.  *  see louis g. kelly -- handbook of numerical methods and 
  16.  *                        applications, p. 68
  17.  *
  18.  *
  19.  * usage:
  20.  *    include poly.inc
  21.  *    declare X,Y as data_array
  22.  *    declare C as const_array
  23.  *    put datapoints into X,Y
  24.  *    call solve_polynomial(degree,X,Y,count,C)
  25.  *    returns array of C constants
  26.  *    degree = 0 finds C[0]
  27.  *    degree = N finds C[0]..C[n]
  28.  *
  29.  *)
  30.  
  31.  
  32. const
  33.    max_degree = 30;   {highest constant subscript}
  34.    max_data = 50;    {maximum number of datapoints}
  35.  
  36. type
  37.    const_array = array[0..max_degree] of real;  {array of constants}
  38.    data_array  = array[0..max_data] of real;    {array of datapoints}
  39.  
  40.  
  41. (* use current interpolation data to find Y for a given X *)
  42. function poly_lookup(x:      real;
  43.                      var C:  const_array;
  44.                      degree: integer): real;
  45. var
  46.    i:  integer;
  47.    y0: real;
  48.    x0: real;
  49.  
  50. begin
  51.    x0 := 1;
  52.    y0 := 0;
  53.    for i := 0 to degree do
  54.    begin
  55.       y0 := y0 + x0 * C[i];
  56.  
  57.       if abs(x0) < 1e17 then   {prevent overflow}
  58.          x0 := x0 * x;
  59.    end;
  60.  
  61.    poly_lookup := y0;
  62. end;
  63.  
  64.  
  65.  
  66. (* solve the polynomial equation for a given table of data
  67.    input in X,Y,count;  passes back array of constants in C;
  68.    calculates constants up to C[min_degree]. *)
  69.  
  70. procedure solve_polynomial(min_degree:  integer;       {input}
  71.                            var X,Y:     data_array;    {input}
  72.                            count:       integer;       {output}
  73.                            var C:       const_array);  {output}
  74. var
  75.    degree:  integer;
  76.    points,u,v,x0: real;
  77.    A,D: const_array;
  78.    P: array[0..max_degree] of const_array;
  79.  
  80.  
  81.    (* subroutine for the computation of P(degree,J), J := 0,...,degree,      *)
  82.    (* from U[degree],V[degree-1],&P[I] := (X - U[I])*P[I-1] - V[I-1]*P[I-2]  *)
  83.    procedure calc1;
  84.    var
  85.       i7,i8: integer;
  86.       j:     integer;
  87.  
  88.    begin
  89.       i8 := degree - 1;
  90.       i7 := 0;
  91.  
  92.       if (degree <> 1) then
  93.          i7 := i8 - 1;
  94.  
  95.       P[degree][0] := - u * P[i8][0] - v * P[i7][0];
  96.  
  97.       if (i8 <> 0) then
  98.          for j := 1 to i8 do
  99.             P[degree][j] := P[i8][j-1] - u * P[i8][j] - v * P[i7][j];
  100.  
  101.       P[degree][degree] := P[i8][i8];
  102.    end;
  103.  
  104.  
  105.    (* subroutine for the evaluation of P0 := P[I0](X0) -- P[I] is *)
  106.    (* the i-th polynomial.                                       *)
  107.    function calc2(i0: integer; x0: real): real;
  108.    var
  109.       j:  integer;
  110.       p0: real;
  111.  
  112.    begin
  113.       p0 := 1;
  114.  
  115.       if (i0 <> 0) then
  116.       begin
  117.          p0 := P[i0][i0];
  118.          for j := i0-1 downto 0 do
  119.             p0 := p0 * x0 + P[i0][j];
  120.       end;
  121.  
  122.       if p0 > 1e18  then p0 := 1e18;
  123.       if p0 < -1e18 then p0 := -1e18;
  124.       calc2 := p0;
  125.    end;
  126.  
  127.  
  128.    (* evaluation of p(i,j), the j-th coefficient of the i-th   *)
  129.    (* orthogonal polynomial. *)
  130.    procedure find_poly_term;
  131.    var
  132.       j,k: integer;
  133.       p0:  real;
  134.       p1:  real;
  135.  
  136.    begin
  137.       (* computation of U[I] *)
  138.       u := 0;
  139.  
  140.       for j := 1 to count do
  141.       begin
  142.          x0 := X[j];
  143.          p0 := calc2(degree-1,x0);
  144.  
  145.          if abs(p0) < 1e17 then       {prevent overflow}
  146.             u := u + x0 * p0 * p0;
  147.       end;
  148.  
  149.       u := u / D[degree-1];
  150.       v := 0;
  151.  
  152.       if (degree <> 1) then
  153.       begin
  154.  
  155.          (* computation of V[I-1] *)
  156.          for j := 1 to count do
  157.          begin
  158.             x0 := X[j];
  159.             p1 := calc2(degree-1,x0);
  160.  
  161.             (* computation and storage of P(I,J), J := 0,...,I *)
  162.             p0 := calc2(degree-2,x0);
  163.  
  164.             if abs(p0) < 1e17 then       {prevent overflow}
  165.                v := v + x0 * p1 * p0;
  166.          end;
  167.  
  168.          v := v / D[degree-2];
  169.       end;
  170.  
  171.       calc1;
  172.  
  173.       (* computation of A(I), the coefficients of the orthogonal *)
  174.       (* basis which determine the fit.  *)
  175.       A[degree] := 0;
  176.       D[degree] := 0;
  177.  
  178.       for j := 1 to count do
  179.       begin
  180.          x0 := X[j];
  181.          p0 := calc2(degree,x0);
  182.          A[degree] := A[degree] + Y[j] * p0;
  183.          D[degree] := D[degree] + p0 * p0;
  184.       end;
  185.  
  186.       A[degree] := A[degree] / D[degree];
  187.  
  188.       (* evaluation of the coefficients C(I) of the fit polynomial. *)
  189.       for k := 0 to degree do
  190.          C[k] := C[k] + A[degree] * P[degree][k];
  191.    end;
  192.  
  193.  
  194.    procedure solve_linear_fit;
  195.    var
  196.       i,j: integer;
  197.       mean: real;
  198.  
  199.    begin
  200.       for i := 0 to max_degree do
  201.       begin
  202.          A[i] := 0;
  203.          C[i] := 0;
  204.          D[i] := 0;
  205.          for j := 0 to max_degree do
  206.             P[i][j] := 0;
  207.       end;
  208.  
  209.       mean := 0;
  210.       for i := 1 to count do
  211.          mean := mean + Y[i];
  212.  
  213.       mean := mean / points;
  214.  
  215.       P[0][0] := 1;
  216.       A[0] := mean;
  217.       C[0] := mean;
  218.       D[0] := points;
  219.    end;
  220.  
  221.  
  222.  
  223. (* body of solve_polynomial *)
  224.  
  225. begin
  226.  
  227.    if (min_degree >= count) then
  228.       min_degree := count-1;
  229.  
  230.    if (min_degree > max_degree-1) then
  231.       min_degree := max_degree-1;
  232.  
  233.    points := int(count);
  234.  
  235.    solve_linear_fit;
  236.  
  237.    for degree := 1 to min_degree do
  238.       find_poly_term;
  239.  
  240. end;
  241.  
  242.