#!../src/tops  -i -s ../sys  -u ../usr
/*
Program Tops - a stack-based computing environment
Copyright (C) 1999-2010  Dale R. Williamson

Author: Dale R. Williamson <dale.williamson@prodigy.net>

File test/lpcoef  October 2010

An example using linear prediction in a different way.

References: 
   Press, W. H., et al, "Numerical Recipes in C," Cambridge
   University Press, second edition, 1999; chapter 13.6.

   File src/wapp.c, functions lpcoef() and lpeval().

----------------------------------------------------------------------*/

// Sun Oct 17 12:14:16 PDT 2010

   if(!X11) exit(<< "lpcoef: require X11 graphics" . nl >>);
   if(missing("sine")) source("mmath.v");
<<
 \ Make a test function similar to the one for man lpcoef:
   1 9.5 2pi star 0 0.001 2100 sine dup "t" book 2nd pry into dt
   1 10.5 2pi star 0 0.001 2100 sine drop plus into S
>>
/*
   Notes for this example.

      The average frequency of test function S is 10 Hz.

      One cycle of 10 Hz has a period of 0.1 seconds.  For step dt
      of 0.001 seconds, there are 100 steps per 10 Hz period.

      This is a different way of looking at linear prediction:

         Model each step separated by 100 steps as an independent series
         of data, where the 100 steps is called the stride, N.  

         From S using stride N, build matrix A containing a data series 
         for linear prediction in each column.

         Use linear prediction serially, to predict the next row of A
         using the prior R rows.

         Finally, use stride N to transform predictions back to the 
         time domain to compare with S.
*/

/* Taking S apart: */
   F = 10;   // frequency, Hz
   P = 1/F;  // period, seconds
   N = P/dt; // stride

/* Each row of A contains data for each period; each column of A con-
   tains data to be treated as a series for linear prediction: */
   A = foldr(S, N)'; // each column is a data series
/*
   eview([[1:cols(A)]' ; A]);

/* How to put S back together: */
   S1 = chain(matrix(A, N));
   if(null?(S - S1)) (<< "S is perfectly back together" . nl >>);
*/
   Cm = 3; // Cm=5 and R=Cm+2 are almost perfect

/* The minimum previous rows to use is Cm: */
   R = Cm+2; // previous rows to use

   B = null(rows(A)+1, cols(A)); // matrix of linear predictions
   ram(A[1:R], [1:R], B);        // first R rows match A

   DO(rows(A)+1, R+1) // serially predict the Ith row of A:
      Ai = A[I-R:I-1];             // using subset Ai
      (C, M) = lpcoef(Ai, Cm);     // compute coefficients
      ram(lpeval(Ai, C, 1), I, B); // evaluate and store prediction
   LOOP;

   S1 = chain(matrix(B, N));     // predictions into time domain
   plot([S , S1[1:rows(S)]], t); // overlay data and predictions

   WAIT_INIT(2, "false"); // delay the ending of this script
   WAIT_BEGIN;

<< 2 idle "*" 72 cats . nl >>
   
