#!../src/tops  -i -s ../sys  -u ../usr
/* File test/bufdemo  March 2006

Symbols tested by this file are: := += @.

Also tested are: 

   on-the-fly zero-based indexing, 

   stepwise reading of a binary OP4 file, 

   storing into part of a matrix: A[, Cpos := m] = H, 

   using parse({" ... "}), the form for gathering unlimited lines for 
   a macro.

Function bufdemo() is an example of reading matrix columns into a buf-
fer and using them.  

Macro bufget() within bufdemo() loads the buffer with a set of columns 
from a matrix on disk.

Bufdemo() uses each consecutive set of columns in a processing loop 
that runs until all column sets have been read.

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

catmsg(no);

function (A) = bufdemo(File, n1) {
/* A matrix from File is buffered to read a subset of columns each time,
   so the entire matrix at once is not required. */

   {
     Hfile = no;
     bufsize = 5; // maximum matrix columns in buffer
   }

// How to cleanly rerun this word when Hfile has been left open:
   if(filetrue(Hfile)) fclose(Hfile);

   open(File, old, binary, "Hfile"); // open handle Hfile for File

/* Get sizes of matrices on Hfile without loading any, from the text 
   returned by _toc4(): */
   T = matread(_toc4(Hfile), 4)'; // column k has MAT(k) properties

   (Rows, Cols) = (@T[1,1], @T[2,1]); // use first MAT for demo, col 1
   H = null(Rows,0); // initialize H to Rows-by-0 (purged)

   n = n1;

   push(xbase); // save index base on local stack

   indexbase(0); // begin zero-based indexing
   Cpos = 0; // zero-based column position pointer

   BEGIN // processing loop 
   WHILE(bufget) // run the following while bufget != 0:

   // Show next set of columns in buffer:
      nl(dot("Next buffer input:"), nl, .m(H));

      A[, Cpos := m] = H; // for demo, just append H to A

      Cpos += m;  // bump the column position pointer (important)
   REPEAT;

   fclose(Hfile); // close Hfile

   indexbase(pull()); // put back saved index base

   return(A);

   { // bufget
     macro(// This local macro gets next group of columns from Hfile.
        parse({" // macros must be postfix
           // Cpos is a zero-based offset so the math is cleaner.

           // The number of columns to get is m:
              m = max(0, @min1([bufsize, n, Cols-Cpos, n-Cpos]));

           // Get m columns from Hfile into buffer H:
              if(m) H = get4c(Hfile, "", Cpos := m);

              return(m); // return the number of columns gotten

           "}), "bufget"
     );
   }
}
//----------------------------------------------------------------------

// Running this test.

   indexbase(1); // use the default, one-based indexing

   closeif("OP4");
   deleteif("TEST.OP4");

// Make a binary OP4 file that bufdemo.bufget() reads:
   open("TEST.OP4", new, binary, "OP4");
   close(put4((B = random(10,28)), OP4), OP4);

   bufdemo.bufsize = 6; // override the default
   M = bufdemo("TEST.OP4", INF); // run buffered input
   nl(dot(nl, "Buffered matrix input from file"));

// M should equal original B:
   if(totals(chain(M - B))==0) dot("Ok bufdemo");
   else dot(" Error in bufdemo");
   nl;

   deleteif("TEST.OP4");
   idle(2);
