
/* Linda (POSYBL) sample program

   does matrix multiplication, A*X = Y, where A is nxn, and X
   and Y are nx1

   A and X will be generated within the program

   there will be a task farm in tuple space, indicating 
   the next row to be multiplied; the tuple ("next row",5), for instance,
   means to multiply row 5; a row >= N means we are all done

*/

int N, /* dimension of matrix */
    *A, /* will serve as the A array after malloc() */
    *X, /* will serve as the X array after malloc() */
    NNodes, /* number of nodes */
    Me,  /* id of this node*/
    Row;  /* current row to multiply */

InitAX()  /* serves as a simple example; in some applications,
             A and X might come from elsewhere, including disk and 
             the tuple space */ 

{  int I,J;

   A = malloc(N*N*sizeof(int));
   X = malloc(N*sizeof(int));
   for (I = 0; I < N; I++)  {
      for (J = 0; J < N; J++)
         A[I*N+J] = I - J;
      X[I] = I;
   }
}

int Mult()

{  int J,DP = 0;

   for (J = 0; J < N; J++) DP += A[Row*N+J] * X[J];
   return DP;
}

Worker()

{  int DotProduct;

   while (1)  {
      in(lstring("next row"),qlint(&Row));
      out(lstring("next row"),lint(Row+1)); 
      if (Row >= N) break;
      DotProduct = Mult();
      out(lstring("y"),lint(Row),lint(DotProduct));  
   }

   /* set up indirect barrier */
   out(lstring("done"));
}

main()

{  int Debug,Value,Node,I;

   /* get general info from front end */
   /* find AND REMOVE a tuple matching "whoami" in the first component,
      and decode the second component into the integer Me */
   in(lstring("whoami"),qlint(&Me));
   /* find BUT DO NOT REMOVE a tuple matching "number of workers"
      in the first component, and decode the second component into
      the integer NNodes */
   rd(lstring("number of workers"),qlint(&NNodes));

   /* get application-specific info from front end */
   /* find BUT DO NOT REMOVE a tuple matching "argument" in the 
      first component and 0 in the second component, and decode the 
      third component into the integer N */
   rd(lstring("argument"),lint(0),qlint(&N));
   /* similarly for Debug */
   rd(lstring("argument"),lint(1),qlint(&Debug));

   while(Debug) ;
  
   /* set up the "next row" tuple */
   if (Me == 0)  out(lstring("next row"),lint(0));

   /* set A and X */
   InitAX();

   /* here is where the main work is done */
   Worker();

   /* node 0 will print the results, but need to make sure everyone 
      is done first (indirect barrier) */
   if (Me == 0)  {
      for (Node = 0; Node < NNodes; Node++)
         in(lstring("done"));
      for (I = 0; I < N; I++)  {
         in(lstring("y"),lint(I),qlint(&Value));
	 printf("%d\n",Value);
      }
   }

   /* to avoid system hanging */
   out(lstring("front end may exit"));

}


