#pragma TASS input 
int L_BOUND;
#pragma TASS input 
int M_BOUND;
#pragma TASS input 
int N_BOUND;
#pragma TASS input {L>=0 && L<=L_BOUND} 
int L; 
#pragma TASS input {M>=0 && M<=M_BOUND} 
int M; 
#pragma TASS input {N>=0 && N<=N_BOUND} 
int N;
#pragma TASS input 
double a[N][L]; 
#pragma TASS input 
double b[L][M]; 
#pragma TASS output 
double c[N][M];

void vecmat(double vector[], double matrix[][], double result[]) {
  int j; int k;
  for (j = 0; j < M; j++) {
    result[j] = 0.0;
    for (k = 0; k < L; k++) result[j] += vector[k]*matrix[k][j];
  }
}

void manager() {
  int count; int i; int j; int source; int tag; double term[L]; double tmp[M];
  for (count = 0; count < NPROCS-1 && count < N; count++)
    send(a[count], count + 1, count + 1);
  for (i = 0; i < N; i++) {
    recv(tmp, any(source), any(tag));  
    for (j = 0; j < M; j++) c[tag-1][j] = tmp[j];
    if (count < N) {
      send(a[count], source, count + 1);
      count++;
    }
  }
  for (i = 1; i < NPROCS; i++) send(term, i, 0); // term signal
}

void worker() {
  double in[L]; double out[M]; int tag;
  recv(in, 0, any(tag));
  while (tag != 0) {
    vecmat(in, b, out);
    send(out, 0, tag);
    recv(in, 0, any(tag));
  }
}

void main() { if (PID == 0) manager(); else worker(); }
